The JDialog isn't showing the JPanel after closing of the dialog and then if the user immediately repeats the action it isn't showing a panel at all but a dialog that is solid black with a small white box in the top left corner. I have tried creating a SSCCE but couldn't develop one. If I remove the window adapter in MainControl class it will just keep adding another panel to the dialog after closing and repeating the opening of the dialog. Below is the code of the SSCCE that I tried creating but it still behaves the same. The code below is the minimal amount needed to run the dialog.
public class CreateAndShowUI {
public static void createUI() {
JFrame frame = new JFrame();
MainPanel mainPanel = new MainPanel();
Dialog dialog = new Dialog();
MainControl mainControl = new MainControl(frame, mainPanel,
dialog);
frame.getContentPane().add(mainPanel.getMainPanel());
frame.setUndecorated(true);
frame.setPreferredSize(new Dimension(1100, 550));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
createUI();
}
}
public class MainControl {
private JFrame frame;
private MainPanel mainPanel;
private Dialog dialog;
public MainControl(JFrame frame, MainPanel panel, Dialog dialog) {
this.frame = frame;
this.mainPanel = panel;
this.dialog = dialog;
mainPanel.getTable().addMouseListener(new MouseListener());
dialog.getDialog().addWindowListener(new DialogWindowListener());
}
public class MouseListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent evt) {
if (evt.getButton() == MouseEvent.BUTTON3) {
dialog.showDialog(new KeywordPanel().getKeywordPanel(),
evt.getXOnScreen(), evt.getYOnScreen());
}
}
}
public class DialogWindowListener extends WindowAdapter {
#Override
public void windowClosing(final WindowEvent event) {
dialog.getDialog().dispose();
dialog.getDialog().removeAll();
}
}
}
public class MainPanel {
private JPanel mainPanel;
private JScrollPane listScrollPane;
private JTable table;
public MainPanel() {
mainPanel = new JPanel(new MigLayout("", "", "[]13[]"));
table = new JTable(new ProductTableModel());
listScrollPane = new JScrollPane(table,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
listScrollPane.setPreferredSize(new Dimension(850, 990));
mainPanel.add(listScrollPane, "cell 0 1");
}
public JPanel getMainPanel() {
return mainPanel;
}
public JTable getTable() {
return table;
}
}
public class KeywordPanel {
private JPanel keywordPanel;
private JLabel searchLbl;
public KeywordPanel() {
searchLbl = new JLabel("KeyWords");
keywordPanel = new JPanel();
keywordPanel.add(searchLbl);
}
public JPanel getKeywordPanel() {
return keywordPanel;
}
}
public class Dialog {
private JDialog dialog = new JDialog();
public Dialog() {
dialog.setLayout(new MigLayout());
}
public void showDialog(JPanel panel, int x, int y) {
dialog.add(panel);
dialog.pack();
dialog.setVisible(true);
}
public JDialog getDialog() {
return dialog;
}
}
public class ProductTableModel extends AbstractTableModel {
private ArrayList<Object> list = new ArrayList<Object>();
private String[] columnNames = { "ID", "Description", "Inventory",
"Minimum Quantity", "Cost", "Order Quantity" };
public ProductTableModel() {
list.add(new Product("Sup", "Sup", "Sup", 10, 20, "null"));
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "<html>ID<br></html>";
case 1:
return "<html>Description<br></html>";
case 2:
return "<html>Inventory<br></html>";
case 3:
return "<html>Minimum<br>Quantity</html>";
case 4:
return "<html>Cost<br></html>";
case 5:
return "<html>Order<br>Quantity</html>";
default:
return null;
}
}
#Override
public int getRowCount() {
return list.size();
}
#Override
public boolean isCellEditable(int row, int column) {
return true;
}
#Override
public Object getValueAt(int row, int column) {
if (list.get(row) instanceof Product) {
Product product = (Product) list.get(row);
switch (column) {
case 0:
return product.getId();
case 1:
return product.getProductDescription();
case 2:
return product.getQtyOnHand();
case 3:
return product.getMinQty();
case 4:
return product.getCost();
case 5:
return product.getOrderQty();
default:
throw new IndexOutOfBoundsException();
}
} else {
return null;
}
}
}
public class Product {
private int minQty;
private double cost;
private String productDescription, id, category, qtyOnHand, orderQty;
public Product(String id, String productDescription, String qtyOnHand,
int minQty, double cost, String orderQty) {
this.setQtyOnHand(qtyOnHand);
this.setOrderQty(orderQty);
this.setId(id);
this.setMinQty(minQty);
this.setCost(cost);
this.setProductDescription(productDescription);
}
public String getQtyOnHand() {
return qtyOnHand;
}
public void setQtyOnHand(String qtyOnHand) {
this.qtyOnHand = qtyOnHand;
}
public String getOrderQty() {
return orderQty;
}
public void setOrderQty(String orderQty) {
this.orderQty = orderQty;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getCost() {
return cost;
}
public void setCost(double cost) {
this.cost = cost;
}
public String getProductDescription() {
return productDescription;
}
public void setProductDescription(String productDescription) {
this.productDescription = productDescription;
}
public int getMinQty() {
return minQty;
}
public void setMinQty(int minQty) {
this.minQty = minQty;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
You should use
dialog.getContentPane().add(panel);
and
dialog.getDialog().getContentPane().removeAll();
And you also must NOT dispose the dialog,
Related
I am new to java swing. I am creating application for patient registration using Swing. There is a button called Clear, that button should clear the input data from the text fields.When button is InputPanel.clear() set the values correctly.But it is not updating.
My classes are below.
MainWindow class create and show the GUI.
public class MainWindow extends JFrame implements ActionListener {
private static final long serialVersionUID = 1905122041950251207L;
transient TableRowSorter<PatientTableModel> sorter;
private PatientListView patientListViewPanel = new PatientListView();
private InputPanel inputPanel = new InputPanel();
private SearchCriteriaPanel searhCriteriaPanel = new SearchCriteriaPanel(this);
public void createAndShowGUI() {
ButtonPanel btnPanel = new ButtonPanel(new MainWindow());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600, 600);
sorter = new TableRowSorter<>(patientListViewPanel.getTableModel());
GridBagLayout gbl = new GridBagLayout();
this.setLayout(gbl);
GridBagConstraints gcon = new GridBagConstraints();
gcon.weightx = 1;
gcon.weighty = 5;
gcon.fill = GridBagConstraints.BOTH;
gcon.gridx = 0;
gcon.gridy = 0;
gcon.gridwidth = 11;
gcon.gridheight = 10;
gbl.setConstraints(inputPanel, gcon);
this.add(inputPanel);
gcon.gridx = 4;
gcon.gridy = 10;
gcon.gridwidth = 11;
gcon.gridheight = 5;
gbl.setConstraints(btnPanel, gcon);
this.add(btnPanel);
gcon.gridx = 0;
gcon.gridy = 22;
gcon.gridwidth = 11;
gcon.gridheight = 10;
gbl.setConstraints(searhCriteriaPanel, gcon);
this.add(searhCriteriaPanel);
gcon.gridx = 0;
gcon.gridy = 33;
gcon.gridwidth = 11;
gcon.gridheight = 10;
gbl.setConstraints(patientListViewPanel, gcon);
this.add(patientListViewPanel);
this.setVisible(true);
inputPanel.getNameText().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if (inputPanel.getNameText().getText().length() > 0)
btnPanel.getSaveBtn().setEnabled(true);
}
});
patientListViewPanel.getTable().addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
getSelectedData();
}
});
}
public MainWindow() {
super("Patient Registration");
}
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
switch (button.getText()) {
case "Save":
patientListViewPanel.getTableModel()
.addData(inputPanel.getData(patientListViewPanel.getTable().getRowCount()));
button.setEnabled(false);
break;
case "Clear":
inputPanel.clear();
break;
case "Search":
SearchCriteria s = new SearchCriteria(searhCriteriaPanel.getSearchNameText().getText(),
searhCriteriaPanel.getBirthYearText().getText(), searhCriteriaPanel.getMaleChkBx().isSelected(),
searhCriteriaPanel.getFemaleChkBx().isSelected());
patientListViewPanel.filter(s);
break;
default:
}
}
}
InputPanel is handle the fields and methods related to input data
public class InputPanel extends JPanel implements PropertyChangeListener {
/**
* clear fields in input panel
*/
public void clear() {
nameText.setText(" ");
phnText.setText("0");
datePickerObj.jDatePicker.getJFormattedTextField().setText("");
maleBtn.setSelected(true);
femaleBtn.setSelected(false);
adrsTxt.setText("");
statusList.setSelectedIndex(4);
}
public InputPanel() {
// fiels will be set to panel
addDataChangedListner();
isDataValid(phnText);
}
public void addDataChangedListner() {
PatientData model = new PatientData();
model.addPropertyChangeListener(this);
nameText.getDocument().addDocumentListener(new DataChangedListener(model, "name"));
phnText.getDocument().addDocumentListener(new DataChangedListener(model, "phnNumber"));
adrsTxt.getDocument().addDocumentListener(new DataChangedListener(model, "address"));
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
String property = evt.getPropertyName();
String newValue = (String) evt.getNewValue();
switch (property) {
case "name":
updatedName = newValue;
break;
case "phnNumber":
updatedPhoneNumber = newValue;
break;
case "address":
updatedAddress = newValue;
break;
default:
}
}
}
Can someone help me to resolve this?
The basic functionality that you are having difficulty with is demonstrated in the following mre: (1)
import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MainWindow extends JFrame{
private InputPanel inputPanel;
private JButton saveBtn;
public void createAndShowGUI() {
inputPanel = new InputPanel();
saveBtn = new JButton("Save");
saveBtn.setEnabled(false);
add(saveBtn, BorderLayout.SOUTH);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(e->clearInput());
add(clearButton, BorderLayout.CENTER);
add(inputPanel, BorderLayout.NORTH);
inputPanel.getNameText().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if (inputPanel.getNameText().getText().length() > 0) {
saveBtn.setEnabled(true);
}
}
});
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
private void clearInput(){
inputPanel.clear();
saveBtn.setEnabled(false);
}
public MainWindow() {
createAndShowGUI();
}
public static void main(String[] args) {
new MainWindow();
}
}
class InputPanel extends JPanel {
JTextField nameText;
/**
* clear fields in input panel
*/
public void clear() {
nameText.setText(""); //use "" and not " " so text length = 0
}
public InputPanel() {
nameText = new JTextField(5);
add(nameText);
}
public JTextField getNameText() {
return nameText;
}
}
However, a better approach is to use the model to implement the change of data :
public class MainWindow extends JFrame implements PropertyChangeListener{
private InputPanel inputPanel;
private JButton saveBtn;
private final PatientData model;
public void createAndShowGUI() {
inputPanel = new InputPanel(model);
saveBtn = new JButton("Save");
saveBtn.setEnabled(false);
add(saveBtn, BorderLayout.SOUTH);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(e->clearInput());
add(clearButton, BorderLayout.CENTER);
add(inputPanel, BorderLayout.NORTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
private void clearInput(){
inputPanel.clear();
}
public MainWindow() {
model = new PatientData();
model.setPropertyChangeListener(this);
createAndShowGUI();
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
updateGui();
}
private void updateGui() {
if(model.getName().trim().isEmpty()){
saveBtn.setEnabled(false);
}else{
saveBtn.setEnabled(true);
}
}
public static void main(String[] args) {
new MainWindow();
}
}
class InputPanel extends JPanel implements DocumentListener{
private final JTextField nameText;
private final PatientData model;
/**
* clear fields in input panel
*/
public void clear() {
nameText.setText(""); //use "" and not " " so text length = 0
updateModel();
}
public InputPanel(PatientData model) {
this.model = model;
nameText = new JTextField("",5);
nameText.getDocument().addDocumentListener(this);
add(nameText);
}
#Override
public void changedUpdate(DocumentEvent e) {
updateModel();
}
#Override
public void removeUpdate(DocumentEvent e) {
updateModel();
}
#Override
public void insertUpdate(DocumentEvent e) {
updateModel();
}
private void updateModel() {
model.setName(nameText.getText());
}
}
class PatientData{
private String name ="";
private PropertyChangeListener listener;
public String getName() {
return name;
}
public void setPropertyChangeListener(PropertyChangeListener listener) {
this.listener = listener;
}
public void setName(String name) {
String oldName = this.name;
this.name = name;
if(listener != null) {
listener.propertyChange(new PropertyChangeEvent(this,"name", oldName, name));
}
}
}
(Test is online here)
(1) Always consider an mre when posting a question or answer.
Well I'm making a simple program to see how works swing elements. Main problem is that when I change the data of table's model not updates the view. I'm using MVP and I've tried "fireTableDataChanged", "fireTableStructureChanged", "repaint", "validate"...
So here's the presenter with "registerStudent" method:
public class StudentPresenter {
private List<Student> students;
private StudentView view;
public StudentPresenter(StudentView view) {
students = new ArrayList<>();
this.view = view;
}
public void run() {
JFrame frame = new JFrame("Students Registrator");
frame.setContentPane(view.getMainFrame());
frame.setLocationRelativeTo(null);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void registerStudent() {
students.add(new Student("Nuevo", 1, 2));
students.add(new Student("Otro", 3, 4));
((TableModel) view.getTable().getModel()).setData(students);
((TableModel) view.getTable().getModel()).refresh();
view.getTable().repaint();
}
}
TableModel with "refresh" method:
public class TableModel extends AbstractTableModel {
private String[] columnNames = {"Nombre", "Edad", "Curso"};
private List<Student> data = new ArrayList<>();
public TableModel() {
data.add(new Student("Ejemplo", 0, 0));
}
public void setData(List<Student> data) {
this.data = data;
}
public void refresh() {
fireTableDataChanged();
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch(columnIndex) {
case 0:
return data.get(rowIndex).getName();
case 1:
return data.get(rowIndex).getAge();
case 2:
return data.get(rowIndex).getCourse();
default:
return null;
}
}
}
StudentView:
public class StudentView {
private StudentPresenter presenter;
private JMenuBar menuBar;
private JScrollPane scrollPane;
private JPanel mainFrame;
private JTable table;
private JButton registerButton;
public StudentView() {
createUIComponents();
}
private void createUIComponents() {
buildMenu();
buildButtons();
buildTable();
}
private void buildMenu() {
menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenuItem exitItem = new JMenuItem("Salir");
exitItem.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
fileMenu.add(exitItem);
JMenu editMenu = new JMenu("Edit");
menuBar.add(fileMenu);
menuBar.add(editMenu);
}
private void buildButtons() {
registerButton = new JButton();
registerButton.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
presenter.registerStudent();
}
});
}
private void buildTable() {
table = new JTable(new TableModel());
table.setFillsViewportHeight(true);
table.setBackground(Color.LIGHT_GRAY);
table.setForeground(Color.gray);
table.setFont(new Font("Arial", Font.PLAIN, 12));
table.setRowHeight(30);
scrollPane = new JScrollPane(table);
}
public void setPresenter(StudentPresenter presenter) {
this.presenter = presenter;
}
public JPanel getMainFrame() {
return mainFrame;
}
public JTable getTable() {
return table;
}
}
I am dynamically creating JTextField based on click event on '+' button. Below is screen shot.
The problem is when I click '+' button, fields created but not shown on JFrame. When I put the cursor on next row under 'item Name', text field becomes visible.
Where is the problem?
Below is my code.
CreateBill()
{
jf = new JFrame("Create Bill");
jf.getContentPane().setLayout(null);
jf.setExtendedState(JFrame.MAXIMIZED_BOTH);
jf.setBounds(0, 0, d1.width, d1.height);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createRow(); // This will create first row by default.
jf.pack();
jf.setVisible(true);
}
private void createRow() {
textField = new JTextField();
textField.setToolTipText("item name");
textField.setBounds(143, 46+j, 288, 20);
textField.setColumns(10);
textField.getDocument().addDocumentListener(new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent e) {
updatePrice();
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
updatePrice();
}
});
AutoCompleteDecorator.decorate(textField, names, true);
jf.getContentPane().add(comboComplete);
jf.getContentPane().add(textField);
comboComplete.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
String ItemSel = textField.getText().trim();
for(Item s:items)
{
if(s.getItemName().equals(ItemSel))
{
textField_1.setText(String.valueOf(s.getUnitPrice()));
}
}
}
});
textFields.add(textField);
textField_1 = new JTextField();
textField_1.setEditable(false);
textField_1.setBounds(639, 46+j, 175, 20);
jf.getContentPane().add(textField_1);
textField_1.setColumns(10);
qty = new JTextField();
qty.setBounds(455, 46+j, 156, 20);
jf.getContentPane().add(qty);
qty.setColumns(10);
qty.getDocument().addDocumentListener(new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent e) {
getTotal();
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
getTotal();
}
});
textFields.add(qty);
textFields.add(textField_1);
textField_3 = new JTextField();
textField_3.setEditable(false);
textField_3.setBounds(1038, 46+j, 156, 20);
jf.getContentPane().add(textField_3);
textField_3.setColumns(10);
textFields.add(textField_3);
JButton button = new JButton("+");
button.setBounds(1235, 45+j, 89, 23);
jf.getContentPane().add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("value of J"+j);
createRow(); // after pressing '+' button i am calling same method again. by changing value of j.
}
});
j=j+22;
jf.setVisible(true);
}
I want my all 4 text fields appear simultaneously.
You need to call repaint() on the container after adding a component to it. You also should call revalidate() too, before calling repaint, since this tells the layout managers to layout the new component, but you're using null layouts, something that you really want to avoid doing.
So my suggestion is to either 1) use nested JPanels with appropriate layout managers, and call revalidate and repaint on your containers after adding or removing components, or 2) yeah, use a Cardlayout to swap views as Andrew Thompson astutely recommends. You can have your second JPanel have a JTextField that uses the same Document as the previous JPanel, so it looks like both are using the same JTextField (as the top JTextField).
On looking further at your images, I have to wonder if a JTable might be an even better solution overall. And yeah, after you start using the layout managers, do also call pack() on your top level window after adding all components and before setting it visible.
For an example of a JTable implementation of this, something along the lines of...
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
#SuppressWarnings("serial")
public class CreateRowGui extends JPanel {
private static final Item[] ITEMS = {
new Item("Light Bulb", 2.00),
new Item("Toilet Paper", 3.00),
new Item("Toothpaste", 1.50),
new Item("Aspirin", 3.75) };
private ItemTableModel tableModel = new ItemTableModel();
private JTable table = new JTable(tableModel);
private AddRowAction addRowAction = new AddRowAction("Add Row", KeyEvent.VK_A);
public CreateRowGui() {
TableCellRenderer moneyRenderer = new DefaultTableCellRenderer() {
private NumberFormat currFormat = NumberFormat.getCurrencyInstance();
#Override
protected void setValue(Object value) {
if (value != null) {
value = currFormat.format(value);
}
super.setValue(value);
}
};
table.getColumnModel().getColumn(2).setCellRenderer(moneyRenderer);
table.getColumnModel().getColumn(3).setCellRenderer(moneyRenderer);
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(addRowAction));
btnPanel.add(new JButton("Remove Row")); // TODO: need Action for this
setLayout(new BorderLayout());
add(new JScrollPane(table));
add(btnPanel, BorderLayout.PAGE_END);
}
class AddRowAction extends AbstractAction {
private NewRowPanel newRowPanel = new NewRowPanel(ITEMS);
public AddRowAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
newRowPanel.reset();
int reply = JOptionPane.showConfirmDialog(table,
newRowPanel.getMainPanel(),
"Select Item and Quantity",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (reply == JOptionPane.OK_OPTION) {
Item item = newRowPanel.getSelectedItem();
int quantity = newRowPanel.getQuantity();
tableModel.addRow(item, quantity);
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("CreateRowGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CreateRowGui());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class NewRowPanel {
private JPanel mainPanel = new JPanel();
private JComboBox<Item> itemsCombo;
private JSpinner quantitySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 20, 1));
#SuppressWarnings("serial")
public NewRowPanel(Item[] items) {
itemsCombo = new JComboBox<>(items);
itemsCombo.setRenderer(new DefaultListCellRenderer(){
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
if (value != null) {
value = ((Item) value).getName();
} else {
value = "";
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
mainPanel.add(new JLabel("Item:"));
mainPanel.add(itemsCombo);
mainPanel.add(Box.createHorizontalStrut(15));
mainPanel.add(new JLabel("Quantity"));
mainPanel.add(quantitySpinner);
}
public void reset() {
itemsCombo.setSelectedIndex(-1);
quantitySpinner.setValue(0);
}
public JPanel getMainPanel() {
return mainPanel;
}
public Item getSelectedItem() {
return (Item) itemsCombo.getSelectedItem();
}
public int getQuantity() {
return (int) quantitySpinner.getValue();
}
}
class ItemTableModel extends AbstractTableModel {
private static final String[] COL_NAMES = { "Item Name", "Quantity", "Unit Price", "Total" };
private static final long serialVersionUID = 1L;
private List<ItemWithCount> itemsWithCount = new ArrayList<>();
#Override
public int getColumnCount() {
return 4;
}
#Override
public int getRowCount() {
return itemsWithCount.size();
}
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return super.getColumnClass(columnIndex);
case 1:
return Integer.class;
case 2:
case 3:
return Double.class;
}
return super.getColumnClass(columnIndex);
}
#Override
public String getColumnName(int column) {
return COL_NAMES[column];
}
#Override
public Object getValueAt(int row, int column) {
ItemWithCount itemWithCount = itemsWithCount.get(row);
switch (column) {
case 0:
return itemWithCount.getItem().getName();
case 1:
return itemWithCount.getCount();
case 2:
return itemWithCount.getItem().getUnitPrice();
case 3:
return itemWithCount.getCount() * itemWithCount.getItem().getUnitPrice();
}
return null;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
ItemWithCount itemWithCount = itemsWithCount.get(rowIndex);
switch (columnIndex) {
case 1:
itemWithCount.setCount((int) aValue);
fireTableRowsUpdated(rowIndex, rowIndex);
break;
default:
break;
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0 || columnIndex == 1;
}
public void addRow(Item item, int quantity) {
ItemWithCount itemWithCount = new ItemWithCount(item, quantity);
itemsWithCount.add(itemWithCount);
int row = itemsWithCount.size() - 1;
fireTableRowsInserted(row, row);
}
private class ItemWithCount {
private Item item;
private int count;
public ItemWithCount(Item item, int count) {
this.item = item;
this.count = count;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Item getItem() {
return item;
}
}
}
class Item {
private String name;
private double unitPrice;
public Item(String name, double unitPrice) {
this.name = name;
this.unitPrice = unitPrice;
}
public String getName() {
return name;
}
public double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
#Override
public String toString() {
return "Item [name=" + name + ", unitPrice=" + unitPrice + "]";
}
}
I have JTable which shows data from arraylist through AbstractTableModel.
What I want to do is when I click (left-click) on row in JTable, I want to show new window where can I see and edit data from row stored in arraylist.
I have MouseListener already written, but it does nothing.
There are main,table and tablemodel classes.
public class MainWindow extends JFrame {
private Controller controller;
private Prihlasovanie prihlasovanie;
private TabulkaSkladnik tabulkaskladnik;
private Okno okno;
public MainWindow() {
super("PROJEKT OOP");
setVisible(true);
setSize(750, 508);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
setMinimumSize(new Dimension(800,500));
controller = new Controller();
tabulkaskladnik = new TabulkaSkladnik();
prihlasovanie = new Prihlasovanie();
tabulkaskladnik.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
Okno okno = new Okno();
okno.setVisible(true);
}
});
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
getContentPane().add(tabbedPane, BorderLayout.NORTH);
tabbedPane.addTab("Prihlasovanie", null , prihlasovanie , null);
tabbedPane.addTab("Skladnik", null , tabulkaskladnik , null);
tabulkaskladnik.setData(controller.getObjednavky());
}
}
public class TabulkaSkladnik extends JTable {
private JTable tabulka;
private SkladnikTableModel tabulkaModel;
public TabulkaSkladnik() {
tabulkaModel = new SkladnikTableModel();
tabulka = new JTable(tabulkaModel);
setLayout(new BorderLayout());
add(new JScrollPane(tabulka),BorderLayout.CENTER);
}
public void setData(List<Objednavka> databaza) {
tabulkaModel.setData(databaza);
}
public void refresh() {
tabulkaModel.fireTableDataChanged();
}
}
public class SkladnikTableModel extends AbstractTableModel {
private List<Objednavka> databaza;
private String[] colNames = {"ID", "Nazov", "Popis", "Meno", "Priezvisko"};
public SkladnikTableModel() {
}
public void setData(List<Objednavka> databaza) {
this.databaza = databaza;
}
public String getColumnName(int column) {
// TODO Auto-generated method stub
return colNames[column];
}
public Class getColumnClass(int col) {
return getValueAt(0,col).getClass();
}
#Override
public int getColumnCount() {
// TODO Auto-generated method stub
return 5;
}
#Override
public int getRowCount() {
return databaza.size();
}
#Override
public Object getValueAt(int riadok, int stlpec) {
Objednavka objednavka = databaza.get(riadok);
switch(stlpec) {
case 0: return objednavka.getId();
case 1: return objednavka.getNazov();
case 2: return objednavka.getOpis();
case 3: return objednavka.getMeno();
case 4: return objednavka.getPriezvisko();
}
return null;
}
}
Thank you for your help! :)
I have a JTable with some rows. How can i block edit row just when radiobutton unlock is selected? Below a small project to use as a working example
Update
ElencoPersoneFrame class
package test;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class ElencoPersoneFrame extends JFrame {
private PersonaTableModel tableModel;
private JTable table;
private JScrollPane scrollPane;
JRadioButton rdbtnFilm = new JRadioButton("Editable");
JRadioButton rdbtnSerieTv = new JRadioButton("Not editable");
public ElencoPersoneFrame()
{
super ("Elenco Persone");
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setSize(400, 250);
ArrayList<Persona> listaPersone = new ArrayList<Persona>();
listaPersone.add(new Persona("Mario", "Rossi", 1972, false));
listaPersone.add(new Persona("Giacomo", "Bianchi", 1946, false));
listaPersone.add(new Persona("Roberto", "Verdi", 1985, true));
tableModel = new PersonaTableModel(listaPersone);
table = new JTable(tableModel);
scrollPane = new JScrollPane(table);
JPanel rdpnl=new radioPanel();
getContentPane().add(rdpnl, BorderLayout.NORTH);
getContentPane().add(scrollPane, BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ElencoPersoneFrame f = new ElencoPersoneFrame();
f.setVisible(true);
}
});
}
}
Persona class
package test;
public class Persona
{
private String nome;
private String cognome;
private int annoNascita;
private boolean disoccupato;
/*costruttore*/
public Persona(String nome, String cognome, int annoNascita, boolean disoccupato) {
this.nome = nome;
this.cognome = cognome;
this.annoNascita = annoNascita;
this.disoccupato = disoccupato;
}
public String getNome() { return nome; }
public String getCognome() { return cognome; }
public int getAnnoNascita() { return annoNascita; }
public boolean isDisoccupato() { return disoccupato; }
public void setNome(String nome) { this.nome = nome; }
public void setCognome(String cognome) { this.cognome = cognome; }
public void setAnnoNascita(int annoNascita) { this.annoNascita = annoNascita; }
public void setDisoccupato(boolean disoccupato) { this.disoccupato = disoccupato; }
}
PersonaTableModel class
package test;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
public class PersonaTableModel extends AbstractTableModel
{
private ArrayList<Persona> listaPersone;
public PersonaTableModel(ArrayList<Persona> listaPersone) {
this.listaPersone = listaPersone;
}
public int getRowCount() {
return listaPersone.size();
}
public int getColumnCount() {
return 4;
}
public String getColumnName(int column) {
switch (column) {
case 0: return "Nome";
case 1: return "Cognome";
case 2: return "Anno nascita";
case 3: return "Disoccupato?";
}
return "";
}
public Class getColumnClass(int column) {
switch (column) {
case 0: return String.class;
case 1: return String.class;
case 2: return Number.class;
case 3: return Boolean.class;
}
return Object.class;
}
public boolean isCellEditable(int row, int column) {
return true;
}
public Object getValueAt(int row, int column) {
Persona p = listaPersone.get(row);
switch (column) {
case 0: return p.getNome();
case 1: return p.getCognome();
case 2: return p.getAnnoNascita();
case 3: return p.isDisoccupato();
}
return null;
}
public void setValueAt(Object value, int row, int column)
{
Persona p = listaPersone.get(row);
switch (column)
{
case 0: p.setNome((String) value); break;
case 1: p.setCognome((String) value); break;
case 2: p.setAnnoNascita((Integer) value); break;
case 3: p.setDisoccupato((Boolean) value); break;
}
}
public void aggiungiPersona(Persona p) {
listaPersone.add(p);
int row = listaPersone.size() - 1;
fireTableRowsInserted(row, row);
}
}
radioPanel class
package test;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class radioPanel extends JPanel implements ActionListener
{
private JRadioButton unlock;
private JRadioButton lock;
private ButtonGroup rdgroup;
public radioPanel()
{
rdgroup=new ButtonGroup();
unlock = new JRadioButton("Editable");
lock = new JRadioButton("Not editable");
rdgroup.add(unlock);
rdgroup.add(lock);
rdgroup.setSelected(unlock.getModel(), true);
this.add(unlock);
this.add(lock);
lock.addActionListener(this);
unlock.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == this.lock)
{
}
if(e.getSource() == this.unlock)
{
}
}
}
So there doesn't seem to be (AFAIK) some magic method to set the table uneditable. What you can do though is create a method in your model, like setEditable(boolean), where you can set a class member boolean editable. Use the same field for isCellEditable. After you change the state, you should fire the table change. Something like
class PersonaTableModel extends AbstractTableModel {
...
private boolean editable = true;
public boolean isEditable() {
return editable;
}
public boolean isCellEditable(int row, int column) {
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
fireTableDataChanged();
}
...
}
You'll also need to way for the ActionListener to get hold of the table model. So you can refactor your radio panel to something like
class radioPanel extends JPanel {
private JRadioButton unlock;
private JRadioButton lock;
private ButtonGroup rdgroup;
...
public ButtonGroup getButtonGroup() {
return rdgroup;
}
public AbstractButton getUnlock() {
return unlock;
}
public AbstractButton getLock() {
return lock;
}
}
This way you can just get the radio buttons from anywhere and add the ActionListener. So you can change you main class code to something like:
radioPanel rdpnl = new radioPanel();
rdpnl.getUnlock().addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
tableModel.setEditable(true);
}
});
rdpnl.getLock().addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
tableModel.setEditable(false);
}
});
getContentPane().add(rdpnl, BorderLayout.NORTH);
Tested, and seems to work as expected.
Aside: Please make note of Java naming convention. Class names should begin with upper case letters i.e. radioPanel → RadioPanel
You need to implement the isCellEditable method for your TableModel:
public boolean isCellEditable(int row, int col)
return false;
See also the tutorials.