I want to put the name of the item that I selected in a JTable in a JLabel that every time that i click a new item in the table the text in the JLabel also change
can someone tell me what should I learn in java to produce that?
You should know very basic Swing programming, and a little deeper understanding of a TableModel, SelectionModel and ListSelectionListener (which is the key to your goal).
A working example:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class TableSelectionToLabel {
private static JTable t = new JTable(new String[][]{{"1,1", "1,2"}, {"2,1", "2,2"}},
new String[]{"1", "2"});
private static JLabel l = new JLabel("Your selction will appear here");
private static JFrame f = new JFrame("Table selection listener Ex.");
private static ListSelectionListener myListener = new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
int col = t.getColumnModel().getSelectionModel().getLeadSelectionIndex();
int row = t.getSelectionModel().getLeadSelectionIndex();
try {
l.setText(t.getModel().getValueAt(row, col).toString());
} catch (IndexOutOfBoundsException ignore) {
}
}
};
public static void main(String[] args) {
t.getSelectionModel().addListSelectionListener(myListener);
t.getColumnModel().getSelectionModel().addListSelectionListener(myListener);
f.getContentPane().add(t, BorderLayout.NORTH);
f.getContentPane().add(l, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
EDIT:
I modified the code to listen to both selection events from the model AND the column model to get a more accurate outcome.
First create the JLabel:
JLabel label = new JLabel();
Then add a listener to the table for selections:
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
label.setText(table.getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
}
});
Related
How can I add elements from different JTextFields to one List. I've tried to put the elements in Strings and add them to the list but thats not working.
You have to add the strings to the list model that backs up the JList. Here is short example code that appends the current JTextField's value to the list whenever you hit ENTER in the text field:
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.BorderLayout;
public final class Example extends JFrame {
public Example() {
setLayout(new BorderLayout());
// Create a list model and populate it with two initial items.
final DefaultListModel<String> model = new DefaultListModel<String>();
model.addElement("Initial 1");
model.addElement("Initial 2");
// Create a JList (wrapped into a JScrollPane) from the model
add(new JScrollPane(new JList<String>(model)), BorderLayout.CENTER);
// Create a JTextField at the top of the frame.
// Whenever you click ENTER in that field, the current string gets
// appended to the list model and will thus show up in the JList.
final JTextField field1 = new JTextField("Field 1");
add(field1, BorderLayout.NORTH);
field1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Append " + field1.getText());
model.addElement(field1.getText());
}
});
// Create a JTextField at the bottom of the frame.
// Whenever you click ENTER in that field, the current string gets
// appended to the list model and will thus show up in the JList.
final JTextField field2 = new JTextField("Field 2");
add(field2, BorderLayout.SOUTH);
field2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Append " + field2.getText());
model.addElement(field2.getText());
}
});
}
public static void main(String[] args) {
final JFrame frame = new Example();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(1); }
});
frame.pack();
frame.setVisible(true);
}
}
I'm using com.toedter.calendar.JDateChooser to search between two dates so I've two jDateChooser components.
jDateChooser1 and jDateChooser2 I want retrieve record after select date from second jDateChooser2 in jTable
I tried write code in constructor it doesn't compile cause empty
String from = jDateChooser1.getDate(); gets null
I can use jButton to search records but I want it on jDateChooser event.
To check if it is working I tried
private void jDateChooser1MouseClicked(java.awt.event.MouseEvent evt){
jLabel1.setText(String.valueOf(jDateChooser1.getDate()));
}
and
private void jDateChooser1MouseReleased(java.awt.event.MouseEvent evt){
jLabel1.setText(String.valueOf(jDateChooser1.getDate()));
}
But it doesn't working either with
jDateChooser1MouseReleased(java.awt.event.MouseEvent evt)
or
jDateChooser1MouseClicked(java.awt.event.MouseEvent evt)
It's working with jButton as I mentioned above but I don't want to use:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
jLabel1.setText(String.valueOf(jDateChooser1.getDate()));
//Working
}
So my previous title was "How implement event for com.toedter.calendar.JDateChooser?"
So now my question is more clear to understand.
Thank you.
You can register a listener using dateChooser.getDateEditor().addPropertyChangeListener(). Then listen for changes in property "date". Try below sample code.
import com.toedter.calendar.JDateChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class JDateChooserSample
{
public static void main(String[] args)
{
JLabel label = new JLabel("No date");
JDateChooser dateChooser = new JDateChooser();
dateChooser.getDateEditor().addPropertyChangeListener(new PropertyChangeListener()
{
#Override
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getPropertyName().equals("date"))
{
label.setText(String.valueOf(dateChooser.getDate()));
}
}
});
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new GridLayout(2, 1));
f.getContentPane().add(dateChooser);
f.getContentPane().add(label);
f.setBounds(300, 200, 400, 300);
f.setVisible(true);
}
}
I have an application with a few tables and a white application background to blend in with used logos. I have set all the backgrounds to white but there is one space that I could not reach so far.
With the standard JTable I am using it is possible to move columns and this is totally fine. However when moving the columns you are still able to see the standard applications color behind the TableHeaders. As displaying in a JScrollPane I thought setting the background of the ScrollPane.getContentHeader() would help but I get an NPE.
Below is a small program that should display the problem:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testsforSO frame = new testsforSO();
frame.setSize(300, 300);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout(0, 0));
JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
String[] columns = new String[] { "ABC", "DEF", "XYZ" };
TableModel tm = new DefaultTableModel(columns, 3);
table = new JTable();
table.setModel(tm);
table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
scrollPane.setViewportView(table);
}
}
When moving one of the three columns you will notice the standard background of your LAF (for me it is the Standard Windows LAF with its beige like color) instead of white eventhough the background of the TableHeader is set to white.
The color is set as well for the parts of the scrollPane width where no tableheaders are displayed and sets the color of the header to the correct color but I cannot figure out how to do so for the space behind the headers.
EDIT: After this seems to get misunderstood, I made a screen of my problem:
Unfortunately you cannot see the cursor, but I am holding the column at its header and dragging it to the right.
your problem are based on code line (because I think that JTable aren't designated to be non_resizable, maybe this is bug maybe its feature)
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
you can to override this painting artefact by, then override the desired Color in Renderer
table.getTableHeader().setBackground(scrollPane.getBackground());
I'd be use JTable.AUTO_RESIZE_OFF, in most case there isn't reason to be restricted to fixed size, my view is to use LayoutManager in all cases, without any restriction(s), e.g.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
//http://stackoverflow.com/questions/40969405/change-background-behind-jtable-tableheaders
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JScrollPane scrollPane = new JScrollPane();
private String[] columns = new String[]{"ABC", "DEF", "XYZ"};
private TableModel tm = new DefaultTableModel(columns, 3);
private JTable table = new JTable(tm);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
testsforSO frame = new testsforSO();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
String[] columns = new String[]{"ABC", "DEF", "XYZ"};
TableModel tm = new DefaultTableModel(columns, 3);
table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.getTableHeader().setBackground(scrollPane.getBackground());
table.getTableHeader().setOpaque(true);
table.setFillsViewportHeight(true);
//table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
scrollPane.setViewportView(table);
add(scrollPane);
}
}
EDIT
Try your program you gave as an answer (including scrollPane.getViewport().setBackground(Color.BLACK);) and run it. Black shows the problem better.
to see
from code (again to use Renderer for painting the Color inside JTables view)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
//http://stackoverflow.com/questions/40969405/change-background-behind-jtable-tableheaders
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
private JScrollPane scrollPane = new JScrollPane();
private String[] columns = new String[]{"ABC", "DEF", "XYZ"};
private TableModel tm = new DefaultTableModel(columns, 3);
private JTable table = new JTable(tm);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
testsforSO frame = new testsforSO();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
String[] columns = new String[]{"ABC", "DEF", "XYZ"};
TableModel tm = new DefaultTableModel(columns, 3);
//table.getTableHeader().setBackground(Color.WHITE); //Does its job
table.getTableHeader().setBackground(Color.BLACK);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setBackground(Color.BLACK);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
scrollPane.getViewport().setBackground(Color.BLACK);
scrollPane.setViewportView(table);
add(scrollPane);
}
}
none of them worked, where the last one brings up an NPE.
The table header is not actually added to the frame until the frame is visible. At this time the scrollpane will get the table header from the table and add the header to the column header of the scrollpane.
So, AFTER the frame is visible you can do:
JTableHeader header = table.getTableHeader();
header.getParent().setBackground(Color.YELLOW);
So the above is required in addition to setting the four levels as suggested by #mKorbel.
You can also check out: Setting JTableHeader holder background colour for a more detailed answer.
I use a JTable with two buttons(Active & Inactive Buttons) . When I click on the Inactive button I hide the first column of the table. Also I try to show the first column when I click on the Active button. But the problem is , when I click on the Active button I couldn't display the first column with its preferred size .
This is the code for hide the first column,
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(0);
expTable.getColumnModel().getColumn(0).setWidth(0);
This is the code for get back fist column,
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(300);
expTable.getColumnModel().getColumn(0).setWidth(100);
First I click on the Inactive button and then I click on the Active button . But this is not working .
Have any idea to how to do above .
private void inactiveButtonActionPerformed(java.awt.event.ActionEvent evt){
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(0);
expTable.getColumnModel().getColumn(0).setWidth(0);
}
private void activeButtonActionPerformed(java.awt.event.ActionEvent evt)
{
expTable.getColumnModel().getColumn(0).setMinWidth(0);
expTable.getColumnModel().getColumn(0).setMaxWidth(300);
expTable.getColumnModel().getColumn(0).setWidth(100);
}
Don't attempt to "hide" a TableColumn by playing with the width. The TableColumn is still part of the table so when the user tabs from column to column, focus will go to the hidden column and disappear from the users view which is very confusing.
Instead you should remove the TableColumn from the TableColumnModel. Then you can add the TableColumn back to the TableColumnModel when needed.
Check out the Table Column Manager which manages this concept for you. If you don't use the full functionality of the class you can use the hideColumn(...) and showColumn(...) to do a simple toggle on the first column.
In the past when I've need to do something like, I've simply removed and re-added the TableColumn
This is a pretty crude example of the concept...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Column 1");
model.addColumn("Column 2");
model.addColumn("Column 3");
model.addColumn("Column 4");
model.setRowCount(100);
JTable table = new JTable(model);
add(new JScrollPane(table));
JToggleButton toggle = new JToggleButton("Toggle");
toggle.addActionListener(new ActionListener() {
private TableColumn column;
#Override
public void actionPerformed(ActionEvent e) {
TableColumnModel columnModel = table.getColumnModel();
if (toggle.isSelected()) {
column = columnModel.getColumn(0);
table.getColumnModel().removeColumn(column);
} else if (column != null) {
columnModel.addColumn(column);
columnModel.moveColumn(columnModel.getColumnCount() - 1, 0);
}
}
});
add(toggle, BorderLayout.SOUTH);
}
}
}
I actually spent sometime putting together a custom TableModel which provide the ability to hide and show columns, which basically wrapped this functionality up in a nice reusable package
In my application everything is distributed.
On a action, application retrieves data from DB and saves in ArrayList<T>.
I create an object of RelativeTableModel where I pass the ArrayList<T>.
public void RelationsClicked() {
ArrayList<Relation> data = myParent.dbOperation.getRelations();
RelativeTableModel tModel = new RelativeTableModel(data); // subclass of AbstractTableModel
myParent.SetBrowsePanelData(tModel);
myParent.SetMainPanel(CashAccountingView.BROWSEPANEL);
}
I have a BrowseListPanel class that has a JTable in JScrollPane. Its instance is already created in the main application.
I pass the model to BrowseListPanel and finally show the panel.
Code:
public void SetBrowsePanelData(AbstractTableModel tModel) {
browsePanel.setTModel(tModel);
}
// BrowseListPanel's Code
public void setTModel(AbstractTableModel tModel) {
this.tModel = tModel; // tModel = AbstractTableModel
}
// Show the Panel
public void SetMainPanel(String panel) {
activePanel = panel;
SetFontSize();
cards.show(mainPanel, panel);
mainPanel.revalidate();
mainPanel.repaint();
}
But I don't see the Table. I believe as the object of BrowseListPanel (containing the JTable) is already created & later the TableModel is added. So some sort of event should be fired in setTModel().
Am I right? If so, what event should be thrown and what should be its implementation.
Invoking setModel() on the table should be sufficient, but you might call fireTableStructureChanged() on the model explicitly as a way to help sort things out.
Also, verify that you are working on the event dispatch thread.
Addendum: Here's an sscce that shows the basic approach.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
/** #see http://stackoverflow.com/questions/8257148 */
public class SwapTableModel extends JPanel {
public SwapTableModel() {
final JTable table = new JTable(Model.Alpha.model);
table.setPreferredScrollableViewportSize(new Dimension(128, 32));
this.add(new JScrollPane(table));
final JComboBox combo = new JComboBox();
for (Model model : Model.values()) {
combo.addItem(model);
}
this.add(combo);
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Model model = (Model) combo.getSelectedItem();
table.setModel(model.model);
}
});
}
private enum Model {
Alpha(), Beta();
private DefaultTableModel model;
private Model() {
Object[] data = {this.toString()};
this.model = new DefaultTableModel(data, 1);
model.addRow(data);
}
}
private void display() {
JFrame f = new JFrame("SwapTableModel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new SwapTableModel().display();
}
});
}
}