JTable : how to get selected cells? - swing

I have a JTable and its TableModel, it works well but what I want to do now is to get the selected cells of it. I thought of doing something like :
int rows = this.getTable().getRowCount();
int columns = this.getTable().getColumnCount();
for(int i = 0 ; i < rows ; i++)
{
for(int j = 0 ; j < columns ; j++)
{
if(table.getCell(i,j).isSelected() //...
}
}
But of course something like this doesn't exist. What should I do instead?

In JTable, you have the
JTable.getSelectedRow()
and
JTable.getSelectedColumn()
You can try combine this two method with a MouseListener and a KeyListener.
With the KeyListener you check if user is pressing the CTRL key, which means that user is selecting cells, then with a mouse listener, for every click you store maybe in a Vector or ArrayList the selected cells:
//global variables
JTable theTable = new JTable();//your table
boolean pressingCTRL=false;//flag, if pressing CTRL it is true, otherwise it is false.
Vector selectedCells = new Vector<int[]>();//int[]because every entry will store {cellX,cellY}
public void something(){
KeyListener tableKeyListener = new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_CTRL){//check if user is pressing CTRL key
pressingCTRL=true;
}
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_CTRL){//check if user released CTRL key
pressingCTRL=false;
}
}
};
MouseListener tableMouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if(pressingCTRL){//check if user is pressing CTRL key
int row = theTable.rowAtPoint(e.getPoint());//get mouse-selected row
int col = theTable.columnAtPoint(e.getPoint());//get mouse-selected col
int[] newEntry = new int[]{row,col};//{row,col}=selected cell
if(selectedCells.contains(newEntry)){
//cell was already selected, deselect it
selectedCells.remove(newEntry);
}else{
//cell was not selected
selectedCells.add(newEntry);
}
}
}
};
theTable.addKeyListener(tableKeyListener);
theTable.addMouseListener(tableMouseListener);
}

table.getSelectedRow() will get selected row.
table.getSelectedColumns() will get selected columns.
getValueAt(rowIndex, columnIndex) will give the value present at the selected row for each column.

JTable has methods to get the selected rows and get the selected columns.

You can use:
int row = table.rowAtPoint(e.getPoint());
int col = table.columnAtPoint(e.getPoint());
You can get the row and column with ( table.getSelectedRow() and table.getSelectedColumn()) but if you selected more than one cell the method table.getSelectedRow() and table.getSelectedColumn() return cell's position of the first cell that was clicked.
On the other hand, table.rowAtPoint(e.getPoint()) and table.columnAtPoint(e.getPoint()) return the exact cell's table that was clicked for the last time.

Related

Libgdx remove and add image from cells

I have this table:
table.add(image1).size(image1.getWidth(), image1.getHeight());
table.add().size(image1.getWidth(), image1.getHeight()).row();
table.add().size(image1.getWidth(), image1.getHeight());
table.add().size(image1.getWidth(), image1.getHeight());
I want, when I clicked on empty cell, image deleted from cell and add to the clicked cell. For example when I clicked on third cell, remove image1 from first cell and add it to the third cell. How can do it?
Update 2:
I wrote this code but when I click on cell1, image1 is not added on table and added on right screen and click on cell0 don't work.
Group group = new Group();
group.addActor(image1);
group.addActor(image2);
group.addActor(image3);
root.add(group).size(16, 16);
root.add(image4).size(image4.getWidth(), image3.getHeight()).row();
root.add(image5).size(image5.getWidth(), image4.getHeight());
root.add(image6).size(image6.getWidth(), image5.getHeight());
stage.addActor(root);
stage.setDebugAll(true);
root.getChildren().get(1).addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
root.getCells().get(1).clearActor();
root.getCells().get(0).clearActor();
root.getCells().get(0).setActor(image1);
group.clear();
group.addActor(image4);
group.addActor(image2);
group.addActor(image3);
root.getCells().get(1).setActor(group);
return true;
}
});
root.getChildren().get(0).addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
root.getCells().get(0).clearActor();
root.getCells().get(1).clearActor();
root.getCells().get(1).setActor(image4);
group.clear();
group.addActor(image1);
group.addActor(image2);
group.addActor(image3);
root.getCells().get(0).setActor(group);
return true;
}
});
Personally, I would set a listener for each table cell that would clear the cell that has 'image1' and then assign the image in the cell that was clicked. Something like:
table.getChildren().get(0).addListener(new ClickListener( // .get(0-3)
Cell<Table> cell = table.getCell(image1);
cell.clearActor();
table.getCells().get(0).setActor(image1); // .get(0-3)
));
Read libgdx's table api page.

How insert or delete row of JPanel consisting of 3 elements

I am using JPanel of three elements row: JLabel, JTextField, JButton.
jPanel.setLayout(new GridLayout(0,3));
I need button of a row to delete its row from JPanel.
for(Pair<JLabel, JTextField> pair: labelTextFieldPairs) {
jPanel.add(pair.getFirst());
jPanel.add(pair.getSecond());
jPanel.add(createDeleteButton());//how to implement that method?
}
Also I have a button to add row to JPanel.
How to do that? Or is it better to use JTable for that?
What if I need to insert row consisting of 3 elements somewhere in the middle of JPanel. How to do that?
JButton addNumberToListButton = new JButton("add number to list");
addNumberToListButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Pair<JLabel, JTextField> pair = new Pair<>(new JLabel(), new JTextField());
labelTextFieldPairs.add(pair);
jPanel.add(pair.getFirst(), labelTextFieldPairs.size());
jPanel.add(pair.getSecond(), labelTextFieldPairs.size());
jPanel.add(createDeleteButton(), labelTextFieldPairs.size());
//will this 3 lines work?
}
});
Deletion operation looks like this:
public void removeRow(int firstComponentInRow) {
labelTextFieldPairs.remove(firstComponentInRow / numberOfColumns);
jPanel.remove(firstComponentInRow);
jPanel.remove(firstComponentInRow);
jPanel.remove(firstComponentInRow);
jPanel.revalidate();
jPanel.repaint();
}
and add operation looks like this:
public void addRow(Pair<JLabel, JFormattedTextField> labelAndTextField) {
labelTextFieldPairs.add(labelAndTextField);
jPanel.add(labelAndTextField.getFirst(), (labelTextFieldPairs.size() - 1) * numberOfColumns);
jPanel.add(labelAndTextField.getSecond(), (labelTextFieldPairs.size() - 1) * numberOfColumns + 1);
jPanel.add(createDeleteButton((labelTextFieldPairs.size() - 1) * numberOfColumns), (labelTextFieldPairs.size() - 1) * numberOfColumns + 2);
jPanel.revalidate();
jPanel.repaint();
}
where labelTextFieldPairs.size() used as insertion index.

How to use KeyReleased event on a cell of JTable

I want to take value from cell of JTable while editing it continuously.So can i apply KeyReleased Event to cell and how?
Don't use a KeyListener.
Instead you can get the default editor for the column which will use a JTextField as the editor. Then you add a DocumentListener to the text field. A DocumentEvent will be generated every time you add/remove text.
public void KeyReleased(MouseEvent e)
{
JTable target = (JTable)e.getSource();
int row = target.getSelectedRow();
int col = target.getSelectedColumn();
Object data = (Object)table.getValueAt(row, col);
JOptionPane.showMessageDialog(null, data);
}

Item renderer - Rendering a row in flex

I have got a datagrid with three columns. I have applied two different renderers on different columns (Say Renderer A at column 1 and Renderer B at column 3).
Now in set Data() of B (column three's renderer) I am changing a Requiredflag on the basis of some condition. In set Data of A (Column 1's renderer), I am checking the RequiredFlag and changing its style accordingly.
The problem is for a Row, A renders before B as it is the first column, so it does not get the updated value of requiredFlag (as the requiredFlag is updated in B).
So can I somehow render the first column's cell again after rendering third column's cell? Or if I can render the whole row again after the value of requiredFlag changes in third column's cell.
See the itemrender as a view, so the renderer itself does not do any computation, just check the value of the object...
If I understood correctly I'll do something like that...
(maybe you need to move the check from set data to updatedisplaylist)
example:
class Test
{
public var col1:String = "Everything";
public var col3:String = "Cars";
public function get color():uint
{
if (col1 == "Everything")
return 0xff0000;
return 0x000000;
}
}
itemrendererA.mxml
override public function set data(value:Object):void
{
super.data = value;
if (super.data != null && super.data is Test)
{
// do what you need to do..
lbl1.text = (super.data as Test).col1;
lbl1.setStyle("color", (super.data as Test).color);
}
}
itemrendererB.mxml
override public function set data(value:Object):void
{
super.data = value;
if (super.data != null && super.data is Test)
{
if ( (super.data as Test).color == 0xff0000)
// do something
else
// do something else
}
}
if that's not what you're looking for, please add some of your code...

How to handle event for nonvisual objects in Flex

I am trying to perform two way binding e.g I have a button (out of many controls), on its selection, I am showing the values of its diff properties(like height, width etc) in some textinput. This one way process works fine.
But the reverse process doesn't work. i.e When I select some button, and try to change its dimension by entering some value in height, width textinputs, the dimension are not changed.
How to know which button was selected by me? How events needs to be handled here ?
private void Form1_Load(object sender, System.EventArgs e)
{
//Create some data and bind it to the grid
dt1 = GetData(1000, 3);
this.UltraGrid1.DataSource = dt1;
//Set the grid's CreationFilter to a new instance of the NumbersInRowSelectors class.
this.UltraGrid1.CreationFilter = new NumbersInRowSelectors();
}
private void UltraGrid1_InitializeLayout(object sender, Infragistics.Win.UltraWinGrid.InitializeLayoutEventArgs e)
{
//Hide the default images that are drawn in the RowSelectors, like the pencil and asterisk, etc.
e.Layout.Override.RowSelectorAppearance.ImageAlpha = Infragistics.Win.Alpha.Transparent;
//Center the text in the RowSelectors.
e.Layout.Override.RowSelectorAppearance.TextHAlign = Infragistics.Win.HAlign.Center;
e.Layout.Override.RowSelectorAppearance.TextVAlign = Infragistics.Win.VAlign.Middle;
//There is no wy to change the width of the RowSelectors.
//Use a smaller font, so that 3-digit numbers will fit.
e.Layout.Override.RowSelectorAppearance.FontData.Name = "Small Fonts";
e.Layout.Override.RowSelectorAppearance.FontData.SizeInPoints = 6;
}
//The NumbersInRowSelectors class. This class Implements a CreationFilter and
//adds a TextUIElement to each RowSelector which displays the row number of
//the row.
public class NumbersInRowSelectors:Infragistics.Win.IUIElementCreationFilter
{
#region Implementation of IUIElementCreationFilter
public void AfterCreateChildElements(Infragistics.Win.UIElement parent)
{
//Don't need to do anything here
}
public bool BeforeCreateChildElements(Infragistics.Win.UIElement parent)
{
//Declare some variables
Infragistics.Win.TextUIElement objTextUIElement;
Infragistics.Win.UltraWinGrid.RowSelectorUIElement objRowSelectorUIElement;
Infragistics.Win.UltraWinGrid.UltraGridRow objRow;
int RowNumber;
//Check to see if the parent is a RowSelectorUIElement. If not,
//we don't need to do anything
if (parent is Infragistics.Win.UltraWinGrid.RowSelectorUIElement)
{
//Get the Row from the RowSelectorsUIElement
objRowSelectorUIElement = (Infragistics.Win.UltraWinGrid.RowSelectorUIElement)parent;
objRow = (Infragistics.Win.UltraWinGrid.UltraGridRow)objRowSelectorUIElement.GetContext(typeof(Infragistics.Win.UltraWinGrid.UltraGridRow));
//Get the Index of the Row, so we can use it as a row number.
RowNumber = objRow.Index;
//Check to see if the TextUIElement is already created. Since
//The RowSelectorsUIElement never has children by default, we
//can just check the count.
if (parent.ChildElements.Count == 0)
{
//Create a new TextUIElement and parent it to the RowSelectorUIElement
objTextUIElement = new Infragistics.Win.TextUIElement(parent, RowNumber.ToString());
parent.ChildElements.Add(objTextUIElement);
}
else
{
//There's already a TextUIElement here, so just set the Text
objTextUIElement = (Infragistics.Win.TextUIElement)parent.ChildElements[0];
objTextUIElement.Text = RowNumber.ToString();
}
//Position the TextUIElement into the RowSelectorUIElement
objTextUIElement.Rect = parent.RectInsideBorders;
//Return True let the grid know we handled this event.
//This doesn't really do anything, since the grid
//does not create any child elements for this object, anyway.
return true;
}
//Return false to let the grid know we did not handle the event.
//This doesn't really do anything, since the grid
//does not create any child elements for this object, anyway.
return false;
}
#endregion
}
}
Create a "currently selected item" member in the class where the button and the text edit are declared.
In the button selection event listener assign the event target to this member. Then use it in the text edit event listener.
For example:
// It's a declaration of the member variable
private var m_current_btn:Button = null;
// It's an event listener for your button
private function on_selection_change(event:Event):void
{
m_current_btn = event.target as Button;
// button_x and button_y are two text edits
button_x.text = m_current_button.x.toString();
button_y.text = m_current_button.y.toString();
}
// Event listener to track changes in the coordinate text inputs
private function on_coordinate_textedit_change(event:Event):void
{
if (m_current_btn != null)
{
m_current_btn.x = parseInt(button_x.text);
m_current_btn.y = parseInt(button_y.text);
}
}