I am performing actions for 2 combo boxes which involves in changing the background color of JLabel. Here is my code,
public class JavaApplication8 {
private JFrame mainFrame;
private JLabel signal1;
private JLabel signal2;
private JPanel s1Panel;
private JPanel s2Panel;
public JavaApplication8()
{
try {
prepareGUI();
} catch (ClassNotFoundException ex) {
Logger.getLogger(JavaApplication8.class.getName())
.log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) throws
ClassNotFoundException
{
JavaApplication8 swingControl = new JavaApplication8();
swingControl.showCombobox1();
}
public void prepareGUI() throws ClassNotFoundException
{
mainFrame = new JFrame("Signal");
mainFrame.setSize(300,200);
mainFrame.setLayout(new GridLayout(3, 0));
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
signal1 = new JLabel("Signal 1",JLabel.LEFT);
signal1.setSize(100,100);
signal1.setOpaque(true);
signal2 = new JLabel("Signal 2",JLabel.LEFT);
signal2.setSize(100,100);
signal2.setOpaque(true);
final DefaultComboBoxModel light = new DefaultComboBoxModel();
light.addElement("Red");
light.addElement("Green");
final JComboBox s1Combo = new JComboBox(light);
s1Combo.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae)
{
if(s1Combo.getSelectedIndex() == 0)
{
signal1.setBackground(Color.RED);
}
else
{
signal1.setBackground(Color.GREEN);
}
}
});
final JComboBox s2Combo1 = new JComboBox(light);
s2Combo1.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae)
{
if(s2Combo1.getSelectedIndex() == 0)
{
signal2.setBackground(Color.RED);
}
else
{
signal2.setBackground(Color.GREEN);
}
}
});
s1Panel = new JPanel();
s1Panel.setLayout(new FlowLayout());
JScrollPane ListScrollPane = new JScrollPane(s1Combo);
s1Panel.add(signal1);
s1Panel.add(ListScrollPane);
s2Panel = new JPanel();
s2Panel.setLayout(new FlowLayout());
JScrollPane List1ScrollPane = new JScrollPane(s2Combo1);
s2Panel.add(signal2);
s2Panel.add(List1ScrollPane);
mainFrame.add(s1Panel);
mainFrame.add(s2Panel);
String[] columnNames = {"Signal 1","Signal 2"};
Object[][] data = {{"1","1"}};
final JTable table = new JTable(data,columnNames);
JScrollPane tablepane = new JScrollPane(table);
table.setFillsViewportHeight(true);
mainFrame.add(tablepane);
mainFrame.setVisible(true);
}
}
When Executed, If I change the item from combo box 1, the 2nd combo box also performs the change. Where did I go wrong?
Yours is a simple solution: don't have the JComboBoxes share the same model. If they share the same model, then changes to the selected item of one JComboBox causes a change in the shared model which changes the view of both JComboBoxes.
I wold use a method to create your combo-jlabel duo so as not to duplicate code. For instance:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class App8 extends JPanel {
private static final int COMBO_COUNT = 2;
private static final String SIGNAL = "Signal";
private List<JComboBox<ComboColor>> comboList = new ArrayList<>();
public App8() {
setLayout(new GridLayout(0, 1));
for (int i = 0; i < COMBO_COUNT; i++) {
DefaultComboBoxModel<ComboColor> cModel = new DefaultComboBoxModel<>(ComboColor.values());
JComboBox<ComboColor> combo = new JComboBox<>(cModel);
add(createComboLabelPanel((i + 1), combo));
comboList.add(combo);
}
}
private JPanel createComboLabelPanel(int index, final JComboBox<ComboColor> combo) {
JPanel panel = new JPanel();
final JLabel label = new JLabel(SIGNAL + " " + index);
label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
label.setOpaque(true);
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
ComboColor cColor = (ComboColor) combo.getSelectedItem();
label.setBackground(cColor.getColor());
}
});
panel.add(label);
panel.add(combo);
return panel;
}
private static void createAndShowGui() {
App8 mainPanel = new App8();
JFrame frame = new JFrame("App8");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum ComboColor {
RED("Red", Color.RED),
GREEN("Green", Color.GREEN);
private String text;
private Color color;
public String getText() {
return text;
}
public Color getColor() {
return color;
}
private ComboColor(String text, Color color) {
this.text = text;
this.color = color;
}
#Override
public String toString() {
return text;
}
}
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.
I am working on a school project using BlueJay and I have created two classes in package Logic which are the Game class, and the VectorGames class.
In my package GUI, I created a class called AddGame and ViewGame class.
The issue that I have encountered is that, when I click the Save Button on Addgame, it saves the file only once. When I try to save it doesn't do or say anything it just stays there returning nothing. Another issue encountered is that on ViewGame, the gameType column is remaining empty ( this is from combo type box )
AddGame code :
package GUI;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import Logic.*;
public class AddGame extends JFrame implements ActionListener{
private JPanel north, south, east, west, center;
private JLabel titleLabel, westLabel, eastLabel;
private JTextField gameNameFld, gameKeyFld;
private JComboBox gameTypeCombo;
private JButton saveButton, clearButton;
private VectorGames vg;
public AddGame(){
super("Adding a Game");
this.setLayout(new BorderLayout());
vg = new VectorGames();
vg.readFromFile();
//north panel
north = new JPanel();
this.add(north,BorderLayout.NORTH);
titleLabel = new JLabel("Add a game below");
titleLabel.setFont(new Font("Verdana",Font.BOLD,20));
titleLabel.setForeground(Color.black);
north.add(titleLabel);
//west and east panels
west = new JPanel();
east = new JPanel();
this.add(west, BorderLayout.WEST);
this.add(east, BorderLayout.EAST);
westLabel = new JLabel(" ");
eastLabel = new JLabel(" ");
west.add(westLabel);
east.add(eastLabel);
//center panel
center = new JPanel();
this.add(center, BorderLayout.CENTER);
center.setLayout(new GridLayout(4,2,0,20));
gameNameFld = new JTextField();
gameKeyFld = new JTextField();
gameTypeCombo = new JComboBox();
gameTypeCombo.setModel(new DefaultComboBoxModel(new String[]
{"<--Select-->", "Arcade", "Puzzle", "Adventure", "Shooter", "Roleplay"}));
center.add(createLabel("Game Name"));
center.add(gameNameFld);
center.add(createLabel("Game Key"));
center.add(gameKeyFld);
center.add(createLabel("Game Type"));
center.add(gameTypeCombo);
//south panel
south = new JPanel();
south.setLayout(new FlowLayout());
this.add(south, BorderLayout.SOUTH);
clearButton = new JButton("Clear");
south.add(clearButton);
clearButton.addActionListener(this);
saveButton = new JButton("Save");
south.add(saveButton);
saveButton.addActionListener(this);
this.setSize(300,400);
this.setLocation(50,50);
this.setVisible(true);
}
private JLabel createLabel(String title){
return new JLabel(title);
}
private void clearFields(){
gameNameFld.setText("");
gameKeyFld.setText("");
gameTypeCombo.setSelectedIndex(0);
}
private boolean validateForm(){
boolean flag = false;
if(gameNameFld.getText().equals("")||gameKeyFld.getText().equals("")||
gameTypeCombo.getSelectedIndex()==0){
flag = true;
}
return flag;
}
public void actionPerformed(ActionEvent event){
if (event.getSource() == clearButton){
clearFields();
}
if(event.getSource() == saveButton){
if(validateForm() == true){
JOptionPane.showMessageDialog(null,"You have empty fields",
"Empty Fields", JOptionPane.ERROR_MESSAGE);
} else if(vg.checkGamebyGameKey(gameKeyFld.getText()) == true){
JOptionPane.showMessageDialog(null,"Game Key already exists!",
"Game Key Check", JOptionPane.ERROR_MESSAGE);
} else {
Game tempGame = new Game(gameNameFld.getText(),gameKeyFld.getText(),
(String)gameTypeCombo.getSelectedItem());
vg.addGame(tempGame);
vg.saveToFile();
JOptionPane.showMessageDialog(null, "Game added successfully!", "Adding a Game",
JOptionPane.INFORMATION_MESSAGE);
clearFields();
}
}
}
}
ViewGame code:
package GUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import Logic.*;
public class ViewGame extends JFrame {
private JTable table;
private VectorGames vg;
public ViewGame(){
super("Viewing Games by Name");
this.setLayout(new BorderLayout());
vg = new VectorGames();
vg.readFromFile();
vg.sortGamesByName();
int numOfGames = vg.getVectorSize();
int count = 0;
Game tempGame = new Game();
String[] tableHeader = {"Game Name", "Game Type", "Game Key"};
Object [][] tableContent = new Object[numOfGames][3];
for(int i = 0; i < numOfGames; i++){
tempGame = vg.getGamesByIndex(count);
tableContent[i][0] = tempGame.getGameName();
tableContent[i][2] = tempGame.getGameType();
tableContent[i][1] = tempGame.getGameKey();
}
table = new JTable (tableContent, tableHeader);
JScrollPane scrollPane = new JScrollPane(table);
table.setPreferredScrollableViewportSize(new Dimension(500, 400));
this.add(table.getTableHeader(), BorderLayout.NORTH);
this.add(table, BorderLayout.CENTER);
this.setSize(500,600);
this.setLocation(100,50);
this.setVisible(true);
}
}
Game code:
package Logic;
import java.io.*;
public class Game implements Serializable{ // Using serializable to allow easy save and read access
//Initializing variables related to Game
private String gameName, gameKey, gameType;
//Creating a constructor with the parameters for class Games
public Game(String gameName, String gamekey, String gameType){
setGameName(gameName);
setGameKey(gameKey);
setGameType(gameType);
}
//Setting up a parameterless constructor for class Games
public Game(){
}
public String getGameName(){//Get Method for gameName
return gameName;
}
public String getGameKey(){//Get Method for gameKey
return gameKey;
}
public String getGameType(){//Get Method for gameType
return gameType;
}
public void setGameName(String gameName){//Set Method for gameName
this.gameName = gameName;
}
public void setGameKey(String gameKey){//Set Method for gameKey
this.gameKey = gameKey;
}
public void setGameType(String gameType){//Set Method for gameType
this.gameType = gameType;
}
public String toString(){
return "Game Name : " + gameName + "\nGame Key : "
+ gameKey + "\nGame Type ; " + gameType;
}
}
VectorGames code:
package Logic;
import java.util.*;
import java.io.*;
import java.lang.*;
public class VectorGames extends IOException{
/* Add a Game, Remove a Game, getVectorGame Size, print allGamesAvailable,
* saveToFile , searchGame and return boolean literal, searchGame and return
* client object, sort games, readFromFile.
*
*/
private Vector<Game> games;
public VectorGames(){
games = new Vector<Game>();
}
//Adding a Game
public void addGame(Game game){
games.add(game);
}
public void deleteGame(Game game){
games.remove(game);
}
public int getVectorSize(){
return games.size();
}
public void clearVector(){
games.clear();
}
public void printGames(){
for(Game tempGame : games){
System.out.println(tempGame.toString());
System.out.println("");
}
}
public Game getGamesByIndex(int i){
Game tempGame = new Game();
if (i < getVectorSize()){
tempGame = games.get(i);
}
return tempGame;
}
public void sortGamesByName(){
Game currentGame = new Game();
Game nextGame = new Game();
Game tempGame = new Game();
for(int i = 0; i < getVectorSize(); i++){
for(int j = 0; j < getVectorSize()-i-1; j++){
currentGame = games.elementAt(j);
nextGame = games.elementAt(j+1);
if(currentGame.getGameName().compareTo(nextGame.getGameName())>0){
tempGame = currentGame;
games.setElementAt(nextGame, j);
games.setElementAt(tempGame, j+1);
}
}
}
}
public boolean checkGamebyGameKey(String gameKey){
boolean flag = false;
for(Game tempGames : games){
if(tempGames .getGameKey().equals(gameKey)){
flag = true;
}
}
return flag;
}
public Game accessGameByGameName(String gameName){
Game foundGameName = new Game();
for(Game tempGames: games){
if(tempGames.getGameName().equals(gameName)){
foundGameName = tempGames;
}
}
return foundGameName;
}
public void saveToFile(){
try{
File f = new File("C:/Users/Denis/Desktop/GameStore/Databases","gameList.obj");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(games);
oos.flush();
oos.close();
}catch (IOException ioe){
System.err.println("Cannot write to file!");
}
}
public void readFromFile(){
try{
File f = new File("C:/Users/Denis/Desktop/GameStore/Databases","gameList.obj");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
games = (Vector<Game>) ois.readObject();
ois.close();
} catch (FileNotFoundException fnfe){
System.err.println("Cannot find file!");
}catch (IOException ioe){
System.err.println("Cannot read from file!");
}catch(ClassNotFoundException cnfe){
System.err.println("Client class cannot be found!");
}
}
}
Main class: GameCenter
public class GameCenter extends JFrame {
public static void main(String... args) {
SwingUtilities.invokeLater(() -> new GameCenter().setVisible(true));
}
public GameCenter() {
super("Game Center");
init();
}
private void init() {
setLayout(new BorderLayout(5, 5));
Model model = new Model();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.add("Add", new AddTabPanel(model));
tabbedPane.add("View", new ViewTabPanel(model));
add(tabbedPane, BorderLayout.CENTER);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(400, 500);
setMinimumSize(new Dimension(400, 500));
setResizable(false);
}
}
Game entity:
final class Game {
private static final Pattern RECORD = Pattern.compile("(?<key>.+)\\|(?<name>.+)\\|(?<type>.+)");
private final String name;
private final String key;
private final String type;
public static Game createFromRecord(String str) {
Matcher matcher = RECORD.matcher(str);
return matcher.matches() ? new Game(matcher.group("name"), matcher.group("key"), matcher.group("type")) : null;
}
public Game(String name, String key, String type) {
this.name = name;
this.key = key;
this.type = type;
}
public String getName() {
return name;
}
public String getKey() {
return key;
}
public String getType() {
return type;
}
public String serialize() {
return String.format("%s|%s|%s", key, name, type);
}
}
Table model:
final class Model extends AbstractTableModel {
private static final long serialVersionUID = 1858846855164475327L;
private final Map<String, Game> keyGame = new TreeMap<>();
private final List<Game> data = new ArrayList<>();
private File file;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public void add(String name, String key, String type) {
keyGame.put(key, new Game(name, key, type));
fireTableDataChanged();
}
public void remove(int rowIndex) {
keyGame.remove(data.get(rowIndex).getKey());
fireTableDataChanged();
}
public void save() throws IOException {
if (file == null)
return;
try (FileWriter out = new FileWriter(file, false)) {
for (Game game : keyGame.values())
out.write(game.serialize() + '\n');
}
}
public void read() throws IOException {
if (file == null)
return;
keyGame.clear();
for (String record : Files.readAllLines(file.toPath())) {
Game game = Game.createFromRecord(record);
if (game != null)
keyGame.put(game.getKey(), game);
}
fireTableDataChanged();
}
private enum Column {
NAME("Game Name", Game::getName),
KEY("Game Key", Game::getKey),
TYPE("Game Type", Game::getType);
private final String title;
private final Function<Game, Object> get;
Column(String title, Function<Game, Object> get) {
this.title = title;
this.get = get;
}
public Object getValue(Game game) {
return get.apply(game);
}
}
// ========== AbstractTableModel ==========
#Override
public void fireTableDataChanged() {
data.clear();
data.addAll(keyGame.values());
super.fireTableDataChanged();
}
// ========== TableModel ==========
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return Column.values().length;
}
#Override
public String getColumnName(int columnIndex) {
return Column.values()[columnIndex].title;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return Column.values()[columnIndex].getValue(data.get(rowIndex));
}
}
AddGame tab panel:
final class AddTabPanel extends JPanel implements ActionListener, DocumentListener {
private final Model model;
private final JTextField nameField = new JTextField();
private final JTextField keyField = new JTextField();
private final JLabel nameLabel = new JLabel("Game Name");
private final JLabel keyLabel = new JLabel("Game Key");
private final JLabel typeLabel = new JLabel("Game Type");
private final JComboBox<String> typeCombo = createGameTypeCombo();
private final JButton openButton = new JButton("Open");
private final JButton saveButton = new JButton("Save");
private final JButton clearButton = new JButton("Clear");
public AddTabPanel(Model model) {
this.model = model;
init();
addListeners();
}
private void init() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = createConstraints();
add(createTitlePanel(), gbc);
add(createMainPanel(), gbc);
add(createButtonPanel(), gbc);
gbc.weighty = 1;
add(Box.createVerticalGlue(), gbc);
onNameFieldChanged();
onKeyFieldChanged();
onTypeComboChanged();
}
private static JPanel createTitlePanel() {
JLabel label = new JLabel("Add a game below");
label.setFont(new Font("Verdana", Font.BOLD, 20));
JPanel panel = new JPanel();
panel.add(label);
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new GridLayout(3, 2, 5, 5));
panel.add(nameLabel);
panel.add(nameField);
panel.add(keyLabel);
panel.add(keyField);
panel.add(typeLabel);
panel.add(typeCombo);
return panel;
}
private static GridBagConstraints createConstraints() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
return gbc;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.add(clearButton);
panel.add(saveButton);
panel.add(openButton);
return panel;
}
private static JComboBox<String> createGameTypeCombo() {
JComboBox<String> combo = new JComboBox<>();
combo.setModel(new DefaultComboBoxModel<>(new String[] { "<--Select-->", "Arcade", "Puzzle", "Adventure", "Shooter", "Roleplay" }));
return combo;
}
private void addListeners() {
clearButton.addActionListener(this);
saveButton.addActionListener(this);
openButton.addActionListener(this);
nameField.getDocument().addDocumentListener(this);
keyField.getDocument().addDocumentListener(this);
typeCombo.addActionListener(this);
}
private void validateFields() {
String name = nameField.getText().trim();
String key = keyField.getText().trim();
int type = typeCombo.getSelectedIndex();
saveButton.setEnabled(!name.isEmpty() && !key.isEmpty() && type != 0);
}
private void onNameFieldChanged() {
nameLabel.setForeground(nameField.getText().trim().isEmpty() ? Color.RED : Color.BLACK);
validateFields();
}
private void onKeyFieldChanged() {
keyLabel.setForeground(keyField.getText().trim().isEmpty() ? Color.RED : Color.BLACK);
validateFields();
}
private void onTypeComboChanged() {
typeLabel.setForeground(typeCombo.getSelectedIndex() == 0 ? Color.RED : Color.BLACK);
validateFields();
}
private void onCleanButton() {
nameField.setText(null);
keyField.setText(null);
typeCombo.setSelectedIndex(0);
validateFields();
}
private void onSaveButton() {
String name = nameField.getText().trim();
String key = keyField.getText().trim();
String type = (String)typeCombo.getSelectedItem();
model.add(name, key, type);
if (model.getFile() == null) {
JFileChooser fileChooser = new JFileChooser();
int res = fileChooser.showSaveDialog(this);
model.setFile(res == JFileChooser.APPROVE_OPTION ? fileChooser.getSelectedFile() : null);
}
try {
model.save();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot save file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
private void onOpenButton() {
JFileChooser fileChooser = new JFileChooser();
int res = fileChooser.showOpenDialog(null);
model.setFile(res == JFileChooser.APPROVE_OPTION ? fileChooser.getSelectedFile() : null);
try {
model.read();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot read file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
// ========== ActionListener ==========
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == typeCombo)
onTypeComboChanged();
else if (e.getSource() == clearButton)
onCleanButton();
else if (e.getSource() == saveButton)
onSaveButton();
else if (e.getSource() == openButton)
onOpenButton();
}
// ========== DocumentListener ==========
#Override
public void insertUpdate(DocumentEvent e) {
if (e.getDocument() == nameField.getDocument())
onNameFieldChanged();
else if (e.getDocument() == keyField.getDocument())
onKeyFieldChanged();
}
#Override
public void removeUpdate(DocumentEvent e) {
if (e.getDocument() == nameField.getDocument())
onNameFieldChanged();
else if (e.getDocument() == keyField.getDocument())
onKeyFieldChanged();
}
#Override
public void changedUpdate(DocumentEvent e) {
}
}
ViewGame tab panel:
final class ViewTabPanel extends JPanel implements ActionListener, PopupMenuListener {
private final Model model;
private final JTable table = new JTable();
private final JPopupMenu popupMenu = new JPopupMenu();
private final JMenuItem deleteItem = new JMenuItem("Delete");
public ViewTabPanel(Model model) {
this.model = model;
init();
addListeners();
}
private void init() {
setLayout(new GridLayout(1, 1));
add(new JScrollPane(table));
popupMenu.add(deleteItem);
table.setComponentPopupMenu(popupMenu);
table.setAutoCreateRowSorter(true);
table.setModel(model);
table.updateUI();
}
private void addListeners() {
popupMenu.addPopupMenuListener(this);
deleteItem.addActionListener(this);
}
// ========== ActionListener ==========
#Override
public void actionPerformed(ActionEvent event) {
if (event.getSource() == deleteItem) {
model.remove(table.getSelectedRow());
try {
model.save();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot save file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
}
// ========== PopupMenuListener ==========
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent event) {
if (event.getSource() == popupMenu) {
SwingUtilities.invokeLater(() -> {
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table));
if (rowAtPoint > -1)
table.setRowSelectionInterval(rowAtPoint, rowAtPoint);
});
}
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent event) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent event) {
}
}
how can I refresh the highlighter in my JTable after changing the search value in the JTextField? It works fine with the JTextArea under the JTextfield, but I the JTable won't refresh the highlighter. Any Suggestions??
This is my Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
public class BeispielTabelle {
JTextField field;
JTextArea textFeld = new JTextArea("Hello World!");
String input="Stefan";
//Titel der Tabelle
String[] title = {"EINS", "ZWEI", "DREI"};
//Tabellendaten
Object[][] playerdata = {
{"34", "Stefan", "Mein Name ist Stefan"},
{"32", "Dirk", "Ich bin der Dirk"},
{"99", "Patrick", "Ich heisse Patrick"},
{"100", "Anna", "Ich bin die Anna"},};
//TableModel
DefaultTableModel model = new DefaultTableModel(playerdata,title);
//Tabelle erstellen
JTable textTable = new JTable(model);
public JPanel erstelleTabelle() {
JPanel totalGUI = new JPanel();
//CellRenderer
SearchRenderer cellRenderer = new SearchRenderer();
//Spaltenbreiten festlegen
textTable.setDefaultRenderer(String.class, cellRenderer);
textTable.getColumnModel().getColumn(0).setCellRenderer(cellRenderer);
textTable.getColumnModel().getColumn(1).setCellRenderer(cellRenderer);
textTable.getColumnModel().getColumn(2).setCellRenderer(cellRenderer);
textTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // Autoresizing abschalten, sonst sind alle Spalten gleich breit:
textTable.getColumnModel().getColumn(0).setPreferredWidth(60);
textTable.getColumnModel().getColumn(1).setPreferredWidth(60);
textTable.getColumnModel().getColumn(2).setPreferredWidth(180);
//das Ganze scrollbar machen
JScrollPane scrollPane = new JScrollPane(textTable);
//TextFeld erstellen
field = new JTextField();
field.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
input = field.getText();
System.out.println(input);
//updateRowHeights();
highlightText();
}
});
totalGUI.add(scrollPane);
totalGUI.add(field);
totalGUI.add(textFeld);
return totalGUI;
}
void highlightText() {
DefaultHighlightPainter yellowPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
Highlighter highlighter = textFeld.getHighlighter();
highlighter.removeAllHighlights();
String text = textFeld.getText();
String pattern = input;
int index = text.indexOf(pattern);
while ( index >= 0 ) {
int len = pattern.length();
try {
highlighter.addHighlight(index, index+len, yellowPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
index = text.indexOf(pattern, index+len);
}
}
private static void createAndShowGUI() {
//create main frame
JFrame mainFrame = new JFrame("");
BeispielTabelle test = new BeispielTabelle();
JPanel totalGUI = new JPanel();
totalGUI = test.erstelleTabelle();
totalGUI.setLayout(new BoxLayout(totalGUI, BoxLayout.Y_AXIS));
//visible mode
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(totalGUI); //integrate main panel to main frame
mainFrame.pack();
mainFrame.setVisible(true);
}
public static void main (String[] args) {
createAndShowGUI();
}//main
}//GUI_main
And this is my SearchRenderer
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.BadLocationException;
import java.awt.*;
public class SearchRenderer extends JTextArea implements TableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 1L;
public SearchRenderer() {}//constructor
BeispielTabelle tabelle = new BeispielTabelle();
String textForSearch=tabelle.input;
#Override
public Component getTableCellRendererComponent (JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column ) {
this.setText((String) value);
if(value != null) {
String string = value.toString();
if(string.contains(textForSearch)){
int indexOf = string.indexOf(textForSearch);
while(indexOf >=0) {
try {
this.getHighlighter().addHighlight(indexOf,indexOf+textForSearch.length(),new javax.swing.text.DefaultHighlighter.DefaultHighlightPainter(Color.GREEN));
} catch (BadLocationException e) {
e.printStackTrace();
}
indexOf = string.indexOf(textForSearch, indexOf+textForSearch.length());
}
}
} else {
this.setText("");
this.getHighlighter().removeAllHighlights();
}
return this;
}
}
Maybe you can use JTable#repaint()
import java.awt.*;
import java.util.Objects;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.text.*;
public final class SearchRendererTest {
private final JTextField field = new JTextField("Stefan");
private final SearchRenderer renderer = new SearchRenderer();
//Titel der Tabelle
private final String[] title = {"EINS", "ZWEI", "DREI"};
//Tabellendaten
private final Object[][] playerdata = {
{"34", "Stefan", "Mein Name ist Stefan"},
{"32", "Dirk", "Ich bin der Dirk"},
{"99", "Patrick", "Ich heisse Patrick"},
{"100", "Anna", "Ich bin die Anna"},
};
private final TableModel model = new DefaultTableModel(playerdata, title);
private final JTable table = new JTable(model);
public JComponent makeUI() {
table.setDefaultRenderer(Object.class, renderer);
field.getDocument().addDocumentListener(new DocumentListener() {
#Override public void insertUpdate(DocumentEvent e) {
fireDocumentChangeEvent();
}
#Override public void removeUpdate(DocumentEvent e) {
fireDocumentChangeEvent();
}
#Override public void changedUpdate(DocumentEvent e) {
/* not needed */
}
});
fireDocumentChangeEvent();
JPanel sp = new JPanel(new BorderLayout(5, 5));
sp.add(new JLabel("regex pattern:"), BorderLayout.WEST);
sp.add(field);
sp.add(Box.createVerticalStrut(2), BorderLayout.SOUTH);
sp.setBorder(BorderFactory.createTitledBorder("Search"));
JPanel p = new JPanel(new BorderLayout(5, 5));
p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
p.add(sp, BorderLayout.NORTH);
p.add(new JScrollPane(table));
return p;
}
private void fireDocumentChangeEvent() {
String pattern = field.getText().trim();
renderer.setPattern(pattern);
table.repaint();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new SearchRendererTest().makeUI());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class SearchRenderer implements TableCellRenderer {
private static final Color BACKGROUND_SELECTION_COLOR = new Color(220, 240, 255);
private final transient Highlighter.HighlightPainter highlightPainter
= new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
private final JTextField field = new JTextField();
private String pattern = "";
private String prev;
public boolean setPattern(String str) {
if (str == null || str.equals(pattern)) {
return false;
} else {
prev = pattern;
pattern = str;
return true;
}
}
public SearchRenderer() {
super();
field.setOpaque(true);
field.setBorder(BorderFactory.createEmptyBorder());
field.setForeground(Color.BLACK);
field.setBackground(Color.WHITE);
field.setEditable(false);
}
#Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
String txt = Objects.toString(value, "");
Highlighter highlighter = field.getHighlighter();
highlighter.removeAllHighlights();
field.setText(txt);
field.setBackground(isSelected ? BACKGROUND_SELECTION_COLOR : Color.WHITE);
if (pattern != null && !pattern.isEmpty() && !pattern.equals(prev)) {
Matcher matcher = Pattern.compile(pattern).matcher(txt);
if (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
try {
highlighter.addHighlight(start, end, highlightPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
return field;
}
}
I'm adding a string to a JList with DefaultListModel and it takes seconds to appear. Sometimes, I may have to click on the JList to have the list appear.
I'm using Eclipse Indigo. When I set a breakpoint after adding the element to JList, execution is fast.
I searched the web and SO for JList slow and they all talk about adding many items to the list. I'm adding the first element to the list.
Here's my code fragments:
private DefaultListModel function_list_model = new DefaultListModel();
private JList list_functions = new JList(function_list_model);
//...
// Initialization code:
JPanel panel_function_list = new JPanel();
panel_function_list.setBounds(10, 53, 541, 220);
panel_functions.add(panel_function_list);
panel_function_list.setLayout(null);
JLabel lblFunctions = new JLabel("Functions");
lblFunctions.setHorizontalAlignment(SwingConstants.CENTER);
lblFunctions.setBounds(235, 11, 99, 14);
panel_function_list.add(lblFunctions);
list_functions.setBorder(new LineBorder(new Color(0, 0, 0)));
list_functions.setBounds(10, 42, 492, 177);
list_functions.setFont(new Font("Courier New", Font.PLAIN, 12));
list_functions.setPreferredSize(new Dimension(0, 150));
list_functions.setMinimumSize(new Dimension(32767, 100));
list_functions.setMaximumSize(new Dimension(32767, 100));
JScrollPane scrollPane_functions = new JScrollPane(list_functions);
scrollPane_functions.setBounds(10, 79, 541, 183);
panel_functions.add(scrollPane_functions);
// Code to add a string:
String burger = new String("burger");
function_list_model.addElement(burger);
I'm also using WindowBuilder with Eclipse.
So how do I improve the performance of JList?
if you want I can to generating new Item from Char[] and to call doClick() for JButton("Fire")
import java.awt.*;
import java.awt.event.*;
import java.util.Date;
import javax.swing.*;
import javax.swing.event.*;
public class ListDemo extends JPanel implements ListSelectionListener {
private JList list;
private DefaultListModel listModel;
private static final String hireString = "Hire";
private static final String fireString = "Fire";
private JButton fireButton;
private JTextField employeeName;
private javax.swing.Timer timer = null;
private int delay = 3;
private int count = 0;
public ListDemo() {
super(new BorderLayout());
listModel = new DefaultListModel();
listModel.addElement("Jane Doe");
listModel.addElement("John Smith");
listModel.addElement("Kathy Green");
list = new JList(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0);
list.addListSelectionListener(this);
list.setVisibleRowCount(5);
JScrollPane listScrollPane = new JScrollPane(list);
JButton hireButton = new JButton(hireString);
HireListener hireListener = new HireListener(hireButton);
hireButton.setActionCommand(hireString);
hireButton.addActionListener(hireListener);
hireButton.setEnabled(false);
fireButton = new JButton(fireString);
fireButton.setActionCommand(fireString);
fireButton.addActionListener(new FireListener());
employeeName = new JTextField(10);
employeeName.addActionListener(hireListener);
employeeName.getDocument().addDocumentListener(hireListener);
String name = listModel.getElementAt(list.getSelectedIndex()).toString();
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.add(fireButton);
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(new JSeparator(SwingConstants.VERTICAL));
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(employeeName);
buttonPane.add(hireButton);
buttonPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
add(listScrollPane, BorderLayout.CENTER);
add(buttonPane, BorderLayout.PAGE_END);
start();
System.out.println(new Date());
}
private void start() {
timer = new javax.swing.Timer(delay * 10, updateCol());
timer.start();
}
public Action updateCol() {
return new AbstractAction("text load action") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
listModel.addElement("Jane Doe");
listModel.addElement("John Smith");
listModel.addElement("Kathy Green");
list.ensureIndexIsVisible(listModel.getSize()-1);
count++;
if (count >= 500) {
timer.stop();
System.out.println("update cycle completed");
System.out.println(new Date());
}
}
};
}
class FireListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int index = list.getSelectedIndex();
listModel.remove(index);
int size = listModel.getSize();
if (size == 0) { //Nobody's left, disable firing.
fireButton.setEnabled(false);
} else { //Select an index.
if (index == listModel.getSize()) {
index--;
}
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
}
}
class HireListener implements ActionListener, DocumentListener {
private boolean alreadyEnabled = false;
private JButton button;
HireListener(JButton button) {
this.button = button;
}
#Override
public void actionPerformed(ActionEvent e) {
String name = employeeName.getText();
if (name.isEmpty() || alreadyInList(name)) {
Toolkit.getDefaultToolkit().beep();
employeeName.requestFocusInWindow();
employeeName.selectAll();
return;
}
int index = list.getSelectedIndex(); //get selected index
if (index == -1) { //no selection, so insert at beginning
index = 0;
} else { //add after the selected item
index++;
}
listModel.insertElementAt(employeeName.getText(), index);
//listModel.addElement(employeeName.getText());
employeeName.requestFocusInWindow();
employeeName.setText("");
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
protected boolean alreadyInList(String name) {
return listModel.contains(name);
}
#Override
public void insertUpdate(DocumentEvent e) {
enableButton();
}
#Override
public void removeUpdate(DocumentEvent e) {
handleEmptyTextField(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
if (!handleEmptyTextField(e)) {
enableButton();
}
}
private void enableButton() {
if (!alreadyEnabled) {
button.setEnabled(true);
}
}
private boolean handleEmptyTextField(DocumentEvent e) {
if (e.getDocument().getLength() <= 0) {
button.setEnabled(false);
alreadyEnabled = false;
return true;
}
return false;
}
}
#Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
if (list.getSelectedIndex() == -1) {
fireButton.setEnabled(false);
} else {
fireButton.setEnabled(true);
}
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("ListDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new ListDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Accessing a JTextField in JTableHeader
How to make JTableHeader as editable. F.e. i make ColumnHeader as JTextField. What must i do to make JTextField editable. See the example:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.event.*;
public class Test extends JFrame {
String[][] cellValues = { { "v00", "v01", "v02" }, { "v10", "v11", "v12" },
{ "v20", "v21", "v22" }, { "v30", "v31", "v32" },
{ "v40", "v41", "v42" }, { "v50", "v51", "v52" } };
String[] columnNames = { "v00", "v01", "v02" };
javax.swing.JTable jTable1 = new javax.swing.JTable(cellValues, columnNames);
public Test() {
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
this.getContentPane().add(new JScrollPane(jTable1), null);
for (int i = 0; i < 3; i++)
jTable1.getColumnModel().getColumn(i)
.setHeaderRenderer(new Renderer());
}
public static void main(String[] args) {
Test frame = new Test();
frame.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
}
class Renderer extends JPanel implements TableCellRenderer {
JLabel label = new JLabel(" ");
JTextField field = new JTextField("%");
public Renderer() {
super(new BorderLayout());
add(label, BorderLayout.NORTH);
add(field, BorderLayout.CENTER);
setBorder(BorderFactory.createEtchedBorder());
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
label.setText(value.toString());
return (JComponent) this;
}
public String toString() {
return label.toString();
}
public void setText(String text) {
label.setText(text);
}
}
Here's a simple approach for making editable headers (no custom renderers or UIs required):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class JTableEditableHeaderDemo implements Runnable
{
private JTable table;
private JTableHeader header;
private JPopupMenu renamePopup;
private JTextField text;
private TableColumn column;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new JTableEditableHeaderDemo());
}
public JTableEditableHeaderDemo()
{
table = new JTable(10, 5);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
header = table.getTableHeader();
header.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent event)
{
if (event.getClickCount() == 2)
{
editColumnAt(event.getPoint());
}
}
});
text = new JTextField();
text.setBorder(null);
text.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
renameColumn();
}
});
renamePopup = new JPopupMenu();
renamePopup.setBorder(new MatteBorder(0, 1, 1, 1, Color.DARK_GRAY));
renamePopup.add(text);
}
public void run()
{
JFrame f = new JFrame("Double-click header to edit");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(table));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private void editColumnAt(Point p)
{
int columnIndex = header.columnAtPoint(p);
if (columnIndex != -1)
{
column = header.getColumnModel().getColumn(columnIndex);
Rectangle columnRectangle = header.getHeaderRect(columnIndex);
text.setText(column.getHeaderValue().toString());
renamePopup.setPreferredSize(
new Dimension(columnRectangle.width, columnRectangle.height - 1));
renamePopup.show(header, columnRectangle.x, 0);
text.requestFocusInWindow();
text.selectAll();
}
}
private void renameColumn()
{
column.setHeaderValue(text.getText());
renamePopup.setVisible(false);
header.repaint();
}
}
There is a complete solution under the following link, looks quite good at the first sight!
How do I create a JTable with editable headers?