I currently have a JComboBox which I'm using as an audio playlist - what I'd like to achieve is a little "remove" button on the right hand side of each item that I can use to remove it from the underlying model, where the circle is:
What would be the best way of achieving this?
I'd like the button to be the same for all items in the JComboBox.
Let me start by saying that this is an interesting question (+1 a while ago).
I had to quickly try and see for myself how difficult it is to achieve the wanted result with JComboBox. The conclusion I got (as #trashgod says in the comment above) was that this object was never designed to have other components or at least it feels like this to me.
Below is a sample that does something what you want. You could use it as a start, but to be honest you should forget about using the JComboBox for this problem.
For no means the sample below presents the right way of approaching the problem. It simply shows the result of my attempts of approaching the problem. The code below doesn't preserve good practice rules e.g. it mixes presentation with functionality (the renderer removes the elements). This is in fact just a hack not a real solution.
import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class ButtonCombo {
private JPanel getContent() throws MalformedURLException {
String[] ids = {"north", "west", "south", "east"};
JComboBox combo = new JComboBox(ids);
Icon removeIcon = new ImageIcon(new URL("http://filesharefreak.org/images/red_x.png"));
combo.setRenderer(new ButtonComboRenderer(removeIcon, combo));
JPanel panel = new JPanel();
panel.add(combo);
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.add(new ButtonCombo().getContent());
JButton button = new JButton("OKOKO");
panel.add(button);
f.setContentPane(panel);
f.setSize(300, 160);
f.setLocation(200, 200);
f.setVisible(true);
} catch (MalformedURLException ex) {
Logger.getLogger(ButtonCombo.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}
class ButtonComboRenderer implements ListCellRenderer {
Icon icon;
JPanel panel;
JLabel label;
JButton button;
public ButtonComboRenderer(Icon removeIcon, final JComboBox combo) {
icon = removeIcon;
label = new JLabel();
button = new JButton(icon);
button.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
panel = new JPanel(new BorderLayout());
panel.add(label);
panel.add(button, BorderLayout.EAST);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (button.getX() < e.getX()) {
System.out.println("button contains the click remove the item");
combo.removeItem(label.getText());
}
}
});
}
//so we will install the mouse listener once
boolean isFirst = true;
#Override
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (isFirst) {
isFirst = false;
list.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
panel.dispatchEvent(e);
e.consume();
}
});
}
String text = (String) value;
label.setText(text);
if(text == null)
button.setIcon(null);
else if(button.getIcon() == null)
button.setIcon(icon);
panel.setBackground(isSelected ? Color.red : Color.white);
panel.setForeground(isSelected ? Color.white : Color.black);
return panel;
}
}
My final recommendation and the way I would do it is:
BUILD YOUR OWN COMPONENT. Make it extensible and modifiable by separating it from the trigger and presentation, where both use JComponents as they come as oppose to using a renderer. In this way you would be able to capture and serve events on the components rather than as in this case all events are captured by the JList used for rendering.
Below is a sample that should help you start. It is not the final solution but it presents lots of the important issues involved in making such component. You should use the presented functionality and wrap it all accordingly in a single component:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class MockJComboBox {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JPanel popupContent = new JPanel(new GridLayout(0, 1));
popupContent.setBackground(Color.GREEN);
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JComboBox(new Object[]{"Content of popupContent panel"}));
final JButton popupCloseButton = new JButton("X");
popupContent.add(popupCloseButton);
final JScrollPane s = new JScrollPane(popupContent);
s.setPreferredSize(new Dimension(popupContent.getPreferredSize().width + s.getVerticalScrollBar().getPreferredSize().width
+ s.getBorder().getBorderInsets(s).left
+ s.getBorder().getBorderInsets(s).right, 100));
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
final JButton popupOpenButton = new JButton();
panel.add(popupOpenButton);
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(panel);
final PopupFactory popupFactory = PopupFactory.getSharedInstance();
popupOpenButton.setAction(new AbstractAction("Open") {
private Popup popup;
private boolean isShown = false;
#Override
public void actionPerformed(ActionEvent e) {
if (isShown) {
popup.hide();
} else {
popup = popupFactory.getPopup(popupOpenButton, s,
popupOpenButton.getLocationOnScreen().x, popupOpenButton.getLocationOnScreen().y + popupOpenButton.getHeight());
popupCloseButton.setAction(new AbstractAction(popupCloseButton.getText()) {
#Override
public void actionPerformed(ActionEvent e) {
isShown = false;
popup.hide();
}
});
popup.show();
}
isShown = !isShown;
}
});
f.pack();
f.setVisible(true);
}
});
}
}
Related
ParentFrame shows ArrayList and one "ADD" Button. Once I click "ADD" Button on ParentFrame, then ChildFrame shows up.
On ChildFrame, I type in a String and click "OK" Button then it should transfer its String to ParentFrame. Finally ParentFrame should be repainted with newly added String.
I'm having trouble with repainting but also I might failed to send String from Child to Parent since Parent didn't get repainted.
I tried several things in two or three other points of view but following code seems like to work but......
I need your help!!
ParentFrame
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.awt.*;
#SuppressWarnings("serial")
public class parentFrame extends JFrame {
ArrayList<String> list = new ArrayList<>(){{add("test1"); add("test2");}};
JButton add;
JPanel big, small;
JLabel content;
childFrame addFrame;
public parentFrame() {
super("parent frame");
super.setLayout(new BorderLayout());
super.setSize(600,600);
big = new JPanel();
for(int i=0; i<list.size(); i++) {
content = new JLabel();
content.setText(list.get(i));
big.add(content);
}
super.add(big, BorderLayout.CENTER);
add = new JButton("ADD");
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
addFrame = new childFrame();
/* By next 3 lines, I'm trying to transfer the value of childFrame's test to this parentFrame's list. */
list.add(addFrame.getTestString());
big.revalidate();
big.repaint();
}
});
super.add(add, BorderLayout.SOUTH);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new parentFrame();
}
}
2.ChildFrame
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class childFrame extends JFrame {
String test;
JTextField name;
JButton ok, cancel;
public childFrame() {
super("child frame");
super.setLayout(new BorderLayout());
super.setSize(400,200);
JPanel centerPanel = new JPanel(new GridLayout(1,1));
centerPanel.setSize(150, 100);
name = new JTextField();
centerPanel.add(name);
JPanel bottomPanel = new JPanel(new FlowLayout());
ok = new JButton("OK");
ok.addActionListener(new OKListener());
super.add(ok);
cancel = new JButton("CANCEL");
cancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
bottomPanel.add(cancel);
bottomPanel.add(ok);
super.add(centerPanel, BorderLayout.CENTER);
super.add(bottomPanel, BorderLayout.SOUTH);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class OKListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
test = name.getText();
dispose();
}
}
public String getTestString() {
return test;
}
}
Your problem is here:
public void actionPerformed(ActionEvent e) {
addFrame = new childFrame();
list.add(addFrame.getTestString());
big.revalidate();
big.repaint();
}
Since your child frame is not a modal window (for example, a JOptionPane is a modal dialog window), it does not halt program flow in the calling window. You call .getTestString() immediately on creation of the child frame but before the user has had any chance to enter in any data (again, because program flow in the calling window is not halted).
The solution is to make your child "frame" in fact a modal JDialog. This will pretty much solve the whole issue. So, don't have the child frame extend from JFrame, but rather extend JDialog, and use the JDialog constructor that makes it modal (see the JDialog API).
e.g.,
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
// note that class names should begin with an upper-case letter
public class ChildFrame extends JDialog {
String test;
JTextField name;
JButton ok, cancel;
public ChildFrame(JFrame parentFrame) {
// the true parameter makes this modal
super(parentFrame, "child frame", true);
Now this dialog window will freeze program flow from the calling code as soon as the dialog is set visible, and the calling code flow won't resume until this dialog is no longer visible.
Also, please have a look at The Use of Multiple JFrames, Good/Bad Practice?
An alternative to this is to continue to use multiple JFrames (not recommended!!), and add a WindowListener to the "child" window, listening for windows closing events, and then getting the information from your dialog in call-back method that is activated when the windows closing event occurs.
For a working example:
import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ParentGuiPanel extends JPanel {
private DefaultListModel<String> listModel = new DefaultListModel<>();
private JList<String> jList = new JList<>(listModel);
private JButton addButton = new JButton("Add");
private JDialog childDialog;
private ChildGuiPanel childPanel = new ChildGuiPanel();
public ParentGuiPanel() {
listModel.addElement("Test 1");
listModel.addElement("Test 2");
jList.setPrototypeCellValue("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
jList.setVisibleRowCount(8);
JScrollPane scrollPane = new JScrollPane(jList);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
addButton.addActionListener(e -> addActionPerformed(e));
addButton.setMnemonic(KeyEvent.VK_A);
JPanel buttonPanel = new JPanel();
buttonPanel.add(addButton);
setLayout(new BorderLayout());
add(scrollPane);
add(buttonPanel, BorderLayout.PAGE_END);
}
private void addActionPerformed(ActionEvent e) {
Window window = null;
if (childDialog == null) {
window = SwingUtilities.getWindowAncestor(this);
if (window == null) {
return;
}
childDialog = new JDialog(window, "Child GUI", ModalityType.APPLICATION_MODAL);
childDialog.add(childPanel);
childDialog.pack();
childDialog.setLocationRelativeTo(window);
}
if (childDialog != null) {
childDialog.setVisible(true);
String text = childPanel.getText();
if (!text.trim().isEmpty()) {
listModel.addElement(text);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame mainGui = new JFrame("Main GUI");
mainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ParentGuiPanel mainPanel = new ParentGuiPanel();
mainGui.add(mainPanel);
mainGui.pack();
mainGui.setLocationRelativeTo(null);
mainGui.setVisible(true);
});
}
}
#SuppressWarnings("serial")
class ChildGuiPanel extends JPanel {
private JTextField textField = new JTextField(15);
private JButton okButton = new JButton("OK");
private JButton cancelButton = new JButton("Cancel");
public ChildGuiPanel() {
okButton.addActionListener(e -> okActionPerformed(e));
cancelButton.addActionListener(e -> cancelActionPerformed(e));
textField.addActionListener(e -> okActionPerformed(e));
okButton.setMnemonic(KeyEvent.VK_O);
cancelButton.setMnemonic(KeyEvent.VK_C);
add(new JLabel("Text: "));
add(textField);
add(okButton);
add(cancelButton);
}
public String getText() {
return textField.getText();
}
private void disposeWindow() {
textField.selectAll();
Window window = SwingUtilities.getWindowAncestor(this);
if (window != null) {
window.dispose();
}
}
private void okActionPerformed(ActionEvent e) {
disposeWindow();
}
private void cancelActionPerformed(ActionEvent e) {
textField.setText("");
disposeWindow();
}
}
Is it possible to create a button that won't be seen until the user clicks another button?
My goal is for the button to be invisible by default rather than when its clicked on. Then become visible when another action is performed. The code below is my original attempt at creating this.
public void but_roll1ActionPerformed(java.awt.event.ActionEvent evt)
{
if (!bal_but.isEnabled() && !gamble_but.isEnabled()) {
but_roll1.setVisible(true);
but_roll1.setEnabled(true);
d1 = diceRoll();
die1_display.setText(String.valueOf(d1));
but_roll1.setEnabled(false);
} else {
but_roll1.setVisible(false);
}
}
Two better strategies:
Put the button in a CardLayout with a second blank panel till needed.
Make the button disabled until the first button is clicked.
I prefer the 2nd as the 'path of least surprise' for the user. YMMV.
Initial view
View after 'effect' button actioned
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class ButtonNotUsableTillAction {
private JComponent ui = null;
ButtonNotUsableTillAction() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new GridLayout(1, 0, 4, 4));
ui.setBorder(new EmptyBorder(4,4,4,4));
// first demo, using card layout
JPanel cardDemoPanel = new JPanel(new GridLayout(1, 0, 2, 2));
cardDemoPanel.setBorder(new TitledBorder("Card Layout"));
ui.add(cardDemoPanel);
JButton actionCardButton = new JButton("Action");
cardDemoPanel.add(actionCardButton);
CardLayout cardLayout = new CardLayout();
JPanel cardLayoutPanel = new JPanel(cardLayout);
cardDemoPanel.add(cardLayoutPanel);
cardLayoutPanel.add(new JPanel(), "panel");
cardLayoutPanel.add(new JButton("Effect"), "button");
cardLayout.show(cardLayoutPanel, "panel");
ActionListener flipCardListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(cardLayoutPanel, "button");
}
};
actionCardButton.addActionListener(flipCardListener);
// first demo, using disabled / enabled
JPanel enabledDemoPanel = new JPanel(new GridLayout(1, 0, 2, 2));
enabledDemoPanel.setBorder(new TitledBorder("Enabled"));
ui.add(enabledDemoPanel);
JButton actionEnabledButton = new JButton("Action");
enabledDemoPanel.add(actionEnabledButton);
JButton effectButton = new JButton("Effect");
enabledDemoPanel.add(effectButton);
effectButton.setEnabled(false);
ActionListener enableComponentListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
effectButton.setEnabled(true);
}
};
actionEnabledButton.addActionListener(enableComponentListener);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ButtonNotUsableTillAction o = new ButtonNotUsableTillAction();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
As #markspace mentioned, you need to revalidate the button's container after setting the button visible:
but_roll1.getParent().revalidate();
I would like to implement the cut method in java to provide the cut and paste functionality.I have already used StringSelection and getSystemClipboard() to provide the cut functionality(code below),but I wanna know how I can use java's inbuilt cut() method for it.
Code for cut functionality.
String t = qu.getText();
StringSelection s = new StringSelection(t);
this.getToolkit().getSystemClipboard().setContents(s, s);
qu.setText("");
I expected something like this to work but it didn't
qu.cut();
Thanks in advance.
If Swing just use the Actions available from the DefaultEditorKit:
new DefaultEditorKit.CutAction()
For example, a small program that uses default actions in a menu, a component-specific pop-up menu, and in buttons:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.text.*;
public class TestActions {
private String[] texts = {
"Hello", "Goodbye", "What the f***?", "Heck if I know", "Peace out man!"
};
private JTextArea textArea = new JTextArea(10, 30);
private Action[] textActions = { new DefaultEditorKit.CutAction(),
new DefaultEditorKit.CopyAction(), new DefaultEditorKit.PasteAction(), };
private JPanel mainPanel = new JPanel();
private JMenuBar menubar = new JMenuBar();
private JPopupMenu popup = new JPopupMenu();
private PopupListener popupListener = new PopupListener();
public TestActions() {
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5));
JMenu menu = new JMenu("Edit");
for (Action textAction : textActions) {
btnPanel.add(new JButton(textAction));
menu.add(new JMenuItem(textAction));
popup.add(new JMenuItem(textAction));
}
menubar.add(menu);
JPanel textFieldPanel = new JPanel(new GridLayout(0, 1, 5, 5));
for (String text: texts) {
JTextField textField = new JTextField(text, 15);
textField.addMouseListener(popupListener);
textFieldPanel.add(textField);
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
((JTextComponent)e.getSource()).selectAll();
}
});
}
textArea.addMouseListener(popupListener);
JScrollPane scrollPane = new JScrollPane(textArea);
JPanel textFieldPanelWrapper = new JPanel(new BorderLayout());
textFieldPanelWrapper.add(textFieldPanel, BorderLayout.NORTH);
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.setLayout(new BorderLayout(5, 5));
mainPanel.add(btnPanel, BorderLayout.NORTH);
mainPanel.add(scrollPane, BorderLayout.CENTER);
mainPanel.add(textFieldPanelWrapper, BorderLayout.EAST);
}
public JComponent getMainPanel() {
return mainPanel;
}
private JMenuBar getMenuBar() {
return menubar;
}
private class PopupListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
private static void createAndShowGui() {
TestActions testActions = new TestActions();
JFrame frame = new JFrame("Test Actions");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(testActions.getMainPanel());
frame.setJMenuBar(testActions.getMenuBar());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
It is because cut() method requires a selection in the text field. Try the following code:
qu.selectAll();
qu.cut();
I'm writing a program in Java where I'm using JTabbedPane. Each tab is associated with a different panel with labels, textfields and a button. I have used GridBagLayout in the panels.
I have added an actionlistener to the button, but when I click it nothing happens.
EDIT: I also have other buttons outside the JTabbedPane which works perfectly fine.
I can see that nothing is happening because I do this:
public void actionPerformed( ActionEvent e ) {
if ( e.getSource() == button ) {
System.out.println("blablabla");
}
and nothing is printed out.
Is there any common problems with using buttons and GridBagLayout/JTabbedPane?
EDIT with SSCCE
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class Hjelp extends JFrame {
private FlowLayout layout;
private JButton button1;
private JButton button2;
private JPanel menu, frontpage;
private JPanel present, previous, something;
public Hjelp() {
layout = new FlowLayout(FlowLayout.CENTER, 10, 20);
setLayout(layout);
setSize(900, 900);
setLocationRelativeTo(null);
setVisible(true);
setPanels();
something = something();
add(something, BorderLayout.CENTER);
something.setVisible(false);
button1 = new JButton("CLICK ME");
add(button1);
buttonListener();
}
private void buttonListener() {
Buttonlistener listener = new Buttonlistener();
button1.addActionListener(listener);
button2.addActionListener(listener);
}
private void setPanels() {
menu = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0));
frontpage = new JPanel();
previous = frontpage;
present = frontpage;
add(menu);
}
public void visiblePanel() {
previous.setVisible(false);
present.setVisible(true);
}
private JPanel something() {
visiblePanel();
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, 1));
JTabbedPane tabbedPane = new JTabbedPane();
JComponent panel1 = tab();
tabbedPane.addTab("Click me", panel1);
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
panel.add(tabbedPane);
return panel;
}
private JComponent tab() {
JPanel panel = new JPanel(false);
panel.setPreferredSize(new Dimension(870, 300));
panel.setLayout(new GridBagLayout());
GridBagConstraints cs = new GridBagConstraints();
cs.fill = GridBagConstraints.HORIZONTAL;
button2 = new JButton("Click me");
cs.gridx = 1;
cs.gridy = 6;
cs.gridwidth = 1;
panel.add(button2, cs);
return panel;
}
private class Buttonlistener implements ActionListener {
#Override
public void actionPerformed( ActionEvent e ) {
if ( e.getSource() == button1 ) {
present = something;
button1.setVisible(false);
something();
previous = something;
}
else if (e.getSource() == button2) {
System.out.println("Blablabla");
}
}
}
public static void main(String [] args) {
final Hjelp vindu = new Hjelp();
vindu.addWindowListener(
new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
} );
}
}
SOLVED
Solution
You don't need the getSource check at all—your listener is (hopefully) attached to just one button, so if it was invoked, that already means the button was clicked. Remove the check and unconditionally print your string. If you still don't see anything, then you have a problem.
You may not have attached a handler to the actual button, and therefore the event will never get called.
Part 1:
ButtonHandler handler = new ButtonHandler();
button.addActionListener( handler );
Part 2:
public class ButtonHandler implements ActionListener
{
#Override
public void actionPerformed(ActionEvent event) {
}
}
ALSO: Java GUI can be finicky, rather than using "e.getSource() == button" you could try "button..isFocusOwner()"
I wrote a program which create a Frame which will display a Control panel and Visual panel.But buttons in control panel is taking too much space. So any body has any idea how to fix it ?? Given is the code.
import java.awt.*;
import java.awt.event.KeyEvent;
import javax.swing.*;
/**
* This class generates and displays a visualization of a Sierpinski
*
*/
public class tOpost
{
private JFrame window;
private JTextField depthTextField;
private Canvas visual;
// declare and initialize default values
private int canvasSize = 512;
/**
* Creates a new window and displays a visualization of a Mandelbrot set
*/
public tOpost()
{
// create new window
window = new JFrame("Sierpinski Visulaizer");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new FlowLayout(FlowLayout.LEFT));
// create main panel
JPanel mainPanel = new JPanel(new GridLayout(0,1));
// create textfields with labels
JPanel depthField = new JPanel(new FlowLayout());
depthField.add(new JLabel("Recursive Depth: "));
depthTextField = new JTextField("");
depthTextField.setPreferredSize(new Dimension(80,25));
depthField.add(depthTextField);
// create comboBoxes
JPanel panel2 = new JPanel();
String[] colorText= {"Blue", "Green"};
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
JPanel[] jPanels = new JPanel[5];
for (int i = 0; i<5; i++) {
JPanel depthColorPanel = new JPanel();
depthColorPanel.add(new JLabel("Color " + (i + 1) + ": "));
JComboBox comboBox = new JComboBox(colorText);
comboBox.setSelectedItem("Blue");
depthColorPanel.add(comboBox);
jPanels[i] = depthColorPanel;
}
JPanel randomColorPanel = new JPanel();
JCheckBox randomColorButton = new JCheckBox("Randomize color at each level");
randomColorButton.setMnemonic(KeyEvent.VK_G);
randomColorButton.setSelected(false);
randomColorPanel.add(randomColorButton);
// create panel for controls
panel2.add(depthField);
for (JPanel panel : jPanels) {
panel2.add(panel);
}
panel2.add(randomColorPanel);
// create button
JPanel germinatePanel = new JPanel(new FlowLayout());
JButton germinateButton = new JButton("Draw");
germinatePanel.add(germinateButton);
mainPanel.add(panel2);
mainPanel.add(germinatePanel);
// create canvas for visualization
visual = new Canvas();
visual.setBackground(Color.BLACK);
visual.setPreferredSize(new Dimension(canvasSize, canvasSize));
mainPanel.setMinimumSize(new Dimension(100, 100));
mainPanel.setPreferredSize(new Dimension(250,canvasSize));
mainPanel.setLocation(750, 250);
// pack widgets and display window
window.add(visual);
window.add(mainPanel);
window.pack();
window.setVisible(true);
System.out.println(mainPanel.getSize().getHeight()+","+ mainPanel.getSize().getWidth());
}
/**
* Draws Triangle.
*
* #param x
* #param y
* #param s
* #param color
*/
/**
* Starts the program by creating a new instance of the Triangle class.
*/
public static void main(String[] args)
{
new tOpost();
}
}
don't mixing AWT Components with Swing JComponents, since is possible, but still caused with a few issues
don't declare for mainPanel.setSize(100,100);, let this is job for proper LayoutManager
JPanel depthField = new JPanel(new FlowLayout());, FlowLayout accepting PreferredSize that came from JComponents
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS)); BoxLayout accepting PreferredSize that returns JComponents
JPanel has implemented FlowLayout by default (without any definitions of LayoutManager)
you have to override proper method for Painting in the standard Java GUI
for AWT Components use method paint()
for Swing JComponents use method paintComponent()
.
.
EDIT
.
.
this code will help you with workaround for JComboBox
code
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.border.LineBorder;
import javax.swing.event.EventListenerList;
class ColorComboBoxEditor implements ComboBoxEditor {
final protected JButton editor;
private EventListenerList listenerList = new EventListenerList();
ColorComboBoxEditor(Color initialColor) {
editor = new JButton("");
editor.setBackground(initialColor);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Color currentBackground = editor.getBackground();
Color color = JColorChooser.showDialog(editor, "Color Chooser", currentBackground);
if ((color != null) && (currentBackground != color)) {
editor.setBackground(color);
fireActionEvent(color);
}
}
};
editor.addActionListener(actionListener);
}
#Override
public void addActionListener(ActionListener l) {
listenerList.add(ActionListener.class, l);
}
#Override
public Component getEditorComponent() {
return editor;
}
#Override
public Object getItem() {
return editor.getBackground();
}
#Override
public void removeActionListener(ActionListener l) {
listenerList.remove(ActionListener.class, l);
}
#Override
public void selectAll() {
}
#Override
public void setItem(Object newValue) {
if (newValue instanceof Color) {
Color color = (Color) newValue;
editor.setBackground(color);
} else {
try {
Color color = Color.decode(newValue.toString());
editor.setBackground(color);
} catch (NumberFormatException e) {
}
}
}
protected void fireActionEvent(Color color) {
Object listeners[] = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ActionListener.class) {
ActionEvent actionEvent = new ActionEvent(editor, ActionEvent.ACTION_PERFORMED, color.toString());
((ActionListener) listeners[i + 1]).actionPerformed(actionEvent);
}
}
}
}
class ColorCellRenderer implements ListCellRenderer {
private DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
private final static Dimension preferredSize = new Dimension(0, 20);
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Color) {
renderer.setBackground((Color) value);
}
if (cellHasFocus || isSelected) {
renderer.setBorder(new LineBorder(Color.DARK_GRAY));
} else {
renderer.setBorder(null);
}
renderer.setPreferredSize(preferredSize);
return renderer;
}
}
class ColorComboBoxEditorRendererDemo {
public ColorComboBoxEditorRendererDemo() {
Color colors[] = {Color.BLACK, Color.BLUE, Color.GREEN, Color.RED, Color.WHITE, Color.YELLOW};
JFrame frame = new JFrame("Color JComboBox");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JComboBox comboBox = new JComboBox(colors);
comboBox.setEditable(true);
comboBox.setRenderer(new ColorCellRenderer());
Color color = (Color) comboBox.getSelectedItem();
ComboBoxEditor editor = new ColorComboBoxEditor(color);
comboBox.setEditor(editor);
frame.add(comboBox, BorderLayout.NORTH);
final JLabel label = new JLabel();
label.setOpaque(true);
label.setBackground((Color) comboBox.getSelectedItem());
frame.add(label, BorderLayout.CENTER);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
Color selectedColor = (Color) comboBox.getSelectedItem();
label.setBackground(selectedColor);
}
};
comboBox.addActionListener(actionListener);
frame.setSize(300, 200);
frame.setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ColorComboBoxEditorRendererDemo colorComboBoxEditorRendererDemo = new ColorComboBoxEditorRendererDemo();
}
});
}
}