I am facing the same problem mentioned here SWT: Table lost selection . I am using ubuntu 12.04 NOT windows. Is there any way to highlight the selected row of a SWT table even after focus lost. I tried adding focus listener to the table and in focus lost I changed the selected item background colour and on focus gain resets the background colour. See the code.
#Override
public void focusLost(FocusEvent e) {
System.out.println("table focus los");
TableItem item = fileListTable
.getItem(fileListTable.getSelectionIndex());
prevSelItemBackground = item.getBackground();
item.setBackground(soureWindow.getSelectionBackground());//Some random colour
System.out.println(fileListTable.getSelectionIndex());
}
#Override
public void focusGained(FocusEvent e) {
System.out.println("table focus gain");
TableItem item = fileListTable
.getItem(fileListTable.getSelectionIndex());
item.setBackground(prevSelItemBackground);
System.out.println(fileListTable.getSelectionIndex());
}
But it is not working. Is there any other solution/workaround for this?
The below snippet can be used:
this.fileListTable.addSelectionListener(new SelectionListener() {
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// Nothing to do
}
#Override
public void widgetSelected(SelectionEvent e) {
int selectionIndex = fileListTable.getSelectionIndex();
TableItem[] items = fileListTable.getItems();
TableItem newItem;
for (int i = 0; i < items.length; i++) {
String first = items[i].getText(0);
String second = items[i].getText(1);
String third = items[i].getText(2);
items[i].dispose();
newItem = new TableItem(fileListTable, SWT.NONE);
newItem.setText(new String[] { first, second, third });
if (i == selectionIndex) {
newItem.setForeground(soureWindow.getSelectionForeground());//Or Anyother color
newItem.setBackground(soureWindow.getSelectionBackground());//Or Anyother color
} else {
newItem.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));//Default foreground color
newItem.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));//Default background color
}
}
}
});
Its is working fine for me but not tested on larger data.
Related
I have an histogram created with JFreeChart API. This is a StackedBar Histogram:
My histogram represents the datas in the JTable on the right. For example the field thea=11 is present two times as Int32 and two times as Int64.
I implemented a mouse event on my chart: when one presses on a bar the corresponding record of the Jtable is selected.
For example if one presses 11.0 bar in the JTable I get:
This is my listener:
chartPanel.addChartMouseListener(new ChartMouseListener() {
#Override
public void chartMouseMoved(ChartMouseEvent arg0) {
}
#Override
public void chartMouseClicked(ChartMouseEvent arg0) {
try{
TableModel model = table.getModel();
CategoryItemEntity entity = (CategoryItemEntity) arg0.getEntity();
Comparable row = entity.getRowKey();
Comparable col = entity.getColumnKey();
System.out.println(String.valueOf(row));
String field = String.valueOf(col);
for(int i = 0; i<model.getRowCount(); i++) {
if(model.getValueAt(i, 0).equals(field)) {
int realRowNumber = table.convertRowIndexToView(i);
table.changeSelection(realRowNumber, 0, false, false);
break;
}
}
}
catch (Exception e) {
System.out.println("No bar selected");
}
}
});
Listener works with a single bar, but it does not work correctly when I have the bar divided in two or more portions.
For example if I press on the blue portion of 11 bar, the selected row in the JTable on the right is the first with 11 as thea, so in my case the selected row is [11,Int32,2] instead of [11,Int64,2] that is the right row to select.
I'm currently trying to add some images from a decoded video to a TableView row and they are not appearing. Only empty TableColumns. The TableView has been designed in JavaFx Scene Builder along with the Label.
Here's what I got so far:
public class MainScreenController implements Initializable {
#FXML
private Label previewBoxLabel;
#FXML
private TableView tableView;
private ObservableList<ImageView> imageList = FXCollections.observableArrayList();
#FXML
public void AddClipBeta(){
//Code which uses an external class in order to decode video (Variables Frames, width and height are not shown but are present in the actual code)
VideoSegment clip = new VideoSegment(0, file.getPath(), 0, Frames, width, height);
//Opens the file in decoding class - ready to output frames
try{clip.openFile();} catch(Exception e){}
//First frame is updated on the preview box
previewBoxLabel.setGraphic(new ImageView(convertToFxImage(clip.getThumbnail())));
System.out.println(file.getPath());
int i =0;
//While loop in test phase to see whether or not 10 frames will be visible in the table
while(i != 10){
//Creates and sets columns to tableView
TableColumn<ImageView, ImageView> col = new TableColumn<ImageView, ImageView>();
col.setPrefWidth(100); //Set width of column
tableView.getColumns().add(col);
col.setCellFactory(new Callback<TableColumn<ImageView, ImageView>, TableCell<ImageView, ImageView>>() {
#Override
public TableCell<ImageView, ImageView> call(TableColumn<ImageView, ImageView> p) {
TableCell<ImageView, ImageView> cell = new TableCell<ImageView, ImageView>(){
};
return cell;
}
});
//Adds current frame to list
imageList.add(new ImageView(convertToFxImage(clip.getThumbnail())));
//Gets next video frame
try{clip.getNextFrame();} catch(Exception e){}
//Updates counter
i++;
}
//Sets list of frames on the table
tableView.setItems(imageList);
}
// There is a problem with this implementation: transparent pixels on the BufferedImage aren't converted to transparent pixels on the fxImage.
public static javafx.scene.image.Image convertToFxImage(java.awt.image.BufferedImage awtImage) {
if (Image.impl_isExternalFormatSupported(BufferedImage.class)) {
return javafx.scene.image.Image.impl_fromExternalImage(awtImage);
} else {
return null;
}
}
I've been struggling understanding how the TableView works the last couple of days and it would be a real breakthrough if we could get to the bottom of this.
Thanks for reading and any help in advance!
When setting a CellFactory, you need to take in to account that it will override some default bevaiours such as setting text and images.
For example. I had to create a ListView of Applications that launched on double click. I had to set a CellFactory in order to add a listener to the mouse click of each individual cell.
applications.setCellFactory(new Callback<TreeView<Application>, TreeCell<Application>>() {
#Override
public TreeCell<Application> call(TreeView<Application> param) {
return new TreeCell<Application>() {
#Override
protected void updateItem(Application item, boolean empty) {
//call the origional update first
super.updateItem(item, empty);
//the root item in my list is null, this check is required to keep a null pointer from happening
if (item != null) {
// text and graphic are stored in the Application object and set.
this.setText(item.getApplicationListName());
this.setGraphic(item.getGraphic());
// registers the mouse event to the cell.
this.setOnMouseClicked((MouseEvent e) -> {
if (e.getClickCount() == 2) {
try {
this.getItem().launch(tabBar);
} catch (UnsupportedOperationException ex) {
Dialogs.create().nativeTitleBar().masthead("Comming Soon™").message("Application is still in development and will be available Soon™").nativeTitleBar().title("Unavailable").showInformation();
}
} else {
e.consume();
}
});
}else if(empty){
this.setText(null);
this.setGraphic(null);
this.setOnMouseClicked(null);
}
}
};
}
});
This was pieced together from some other code so if there is anything else you would like explained, let me know!
I managed to sort this out with the help of you guys. Basically, what I did was make a class with a bunch of setters and getters and a constructor that takes in ImageViews and sets it to a variable in the class via it's constructors. Then I went back to my code and added the following:
Class with Getters and Setters:
import javafx.scene.image.ImageView;
public class tableDataModel {
private ImageView image;
public tableDataModel(ImageView image){
this.image = image;
}
public ImageView getImage(){
return image;
}
public void setImage(ImageView image){
this.image = image;
}
}
Code from MainScreenController:
TableColumn<tableDataModel, ImageView> col = new TableColumn<>();
tableView.getColumns().add(col);
imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getThumbnail()))));
col.setPrefWidth(50);
col.setCellValueFactory(new PropertyValueFactory<tableDataModel, ImageView>("image"));
int i = 0;
while (i != 10) {
try {
imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getNextFrame()))));
} catch (Exception e) {
}
i++;
}
tableView.setItems(imageList);
I'm having some trouble using two comboboxes to affect the state of one item. Each combo box has a value between 1 and 99, I'm trying to change the values in each, combine them, then display this value on a jlabel. So far I can only the first combobox seems to impact the formula. I have simplified it to the following and thanks for any help :)
private int value1int, value2int;
value1.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent ex)
{
if (ex.getStateChange() == ItemEvent.SELECTED)
{
// assume single selection
int value1int = (Integer)ex.getItemSelectable().getSelectedObjects()[0];
}
}
});
value2.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent exs)
{
if (exs.getStateChange() == ItemEvent.SELECTED)
{
// assume single selection
int value2int = (Integer)exs.getItemSelectable().getSelectedObjects()[0];
}
}
});
overallValue2.setText((Integer.toString(value1int + value2int)));
overallValue2.revalidate();
you have to do something like that:
public class GUI extends JFrame ...
private int labelVal;
...
// combobox events - The same code to both comboboxes must works
public void itemStateChanged(ItemEvent exs)
{
if (exs.getStateChange() == ItemEvent.SELECTED)
{
// assume single selection
int aux = (Integer)combobox1.getSelectedItem()+(Integer)combobox2.getSelectedItem();
int labelVal= aux;
}
}
Them refresh the screen
I have a situation where I have a popup menu created when a JTable is right clicked on. Standard way of creating the popup menu:
aJTable.setComponentPopupMenu(rightClickMenu);
Now afterwards in the action that gets registered, I am unable to find out which cell was right clicked on to get that popup menu to appear.
rightClickMenuItem.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Work out what cell was right clicked to generate the menu
}
});
Any ideas on how you do this?
Astonishing fact: with a componentPopupMenu installed, a mouseListener never sees the mouseEvent that is the popupTrigger (reason is that showing the componentPopup is handled globally by a AWTEventListener installed by BasicLookAndFeel, and that listener consumes the event).
The only place which sees the mousePosition of that trigger is the getPopupLocation(MouseEvent), so the only reliable way to get hold of it (for doing location dependent config/actions) is #Mad's suggestion to override that method and store the value somewhere for later use.
The snippet below uses a clientProperty as storage location:
final JTable table = new JTable(new AncientSwingTeam()) {
#Override
public Point getPopupLocation(MouseEvent event) {
setPopupTriggerLocation(event);
return super.getPopupLocation(event);
}
protected void setPopupTriggerLocation(MouseEvent event) {
putClientProperty("popupTriggerLocation",
event != null ? event.getPoint() : null);
}
};
JPopupMenu popup = new JPopupMenu();
Action action = new AbstractAction("show trigger location") {
#Override
public void actionPerformed(ActionEvent e) {
JPopupMenu parent = (JPopupMenu) SwingUtilities.getAncestorOfClass(
JPopupMenu.class, (Component) e.getSource());
JTable invoker = (JTable) parent.getInvoker();
Point p = (Point) invoker.getClientProperty("popupTriggerLocation");
String output = p != null ? "row/col: "
+ invoker.rowAtPoint(p) + "/" + invoker.columnAtPoint(p) : null;
System.out.println(output);
}
};
popup.add(action);
popup.add("dummy2");
table.setComponentPopupMenu(popup);
#MadProgrammer's suggestion of getPopupLocation looked promising, but I couldn't work out how to get the information across between the table and the actionEvent...
I got around this by making sure that the row was selected when you rightclicked on it -> since the popup menu prevents the selection of the row, you can add in a mouse listener that makes sure the row gets selected no matter what click (left or right) is pressed.
aTable.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
int r = aTable.rowAtPoint(e.getPoint());
if (r >= 0 && r < clt.getRowCount()) {
aTable.setRowSelectionInterval(r, r);
} else {
aTable.clearSelection();
}
}
});
This means that in the rightClickMenuItem's action listener, you can grab the table's selected cell / row
rightClickMenuItem.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
aTable.get details about the selected one....
}
});
Too easy! Thanks everyone for the help.
JTable has methods
int row = rowAtPoint(p);
int col = columnAtPoint(p);
So pass the MouseEvent's point and use the values
Add a MouseListener and store the last right click point somewhere.
I added a mouse clicked listner to my jtable, when i double click the row, will pop up an window accordingly.
jTable.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
double amount = Double.parseDouble(jTable.getValueAt(getSelectedRow(), 4).toString());
String remarks = jTable.getValueAt(getSelectedRow(), 3).toString();
String transactionID = jTable.getValueAt(getSelectedRow(), 1).toString();
new EditFrame(...)
}
});
This code I used to retrieve the row selected row.
public int getSelectedRow() {
jTable.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
int viewRow = jTable.getSelectedRow();
selectedRow = viewRow;
System.out.println(viewRow);
}
});
return selectedRow;
}
In my case, I realised when I clicked the second row in the first time, I get null for selectedRow, only when I select first row then second row, I then can get the correct data. And If I removed the mouse listener the problem then be solved. Is it because I doing something wrong at the mouse click listener?
If you just want to know what row was clicked then you don't need the selection listener. Just use:
table.rowAtPoint();
You're doing it the wrong way. Remove your current getSelectedRow() method completely and never try to code something similar. Here is a better version:
jTable.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
int selectedRow = jTable.getSelectedRow();
double amount = Double.parseDouble(jTable.getValueAt(selectedRow, 4).toString());
String remarks = jTable.getValueAt(selectedRow, 3).toString();
String transactionID = jTable.getValueAt(selectedRow, 1).toString();
new EditFrame(...)
}
});