I'm doing an application that play a video and in a JLabel i'm showing timecode of video. Also have a JCombobox that allows to change subtitles of the video.
That JCombobox has a ListCellRenderer that change default output of each item of combobox.
Problem is that each time the JLabel change its value the JCombobox is rendered again.
I think this is a waste of resources there is some way of change that behavior?.
There is the code relative to the JComboBox. The JLabel is modified by a swing.Timer each second.
JComboBox comboBox = new JComboBox<>();
comboBox.setEditable(false);
DefaultComboBoxModel<File> defaultComboBox = new DefaultComboBoxModel<>();
for (File f : Player.capitulo.getFicheros()) {
if (f.getAbsolutePath().endsWith(".srt")) {
System.out.println(f.getAbsolutePath());
defaultComboBox.addElement(f);
}
}
comboBox.setModel(defaultComboBox);
comboBox.setRenderer(new ListRenderer());
public class ListRenderer implements ListCellRenderer<File> {
protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
#Override
public Component getListCellRendererComponent(JList<? extends File> list,
File value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel renderer = new JLabel();
// JLabel renderer = (JLabel) defaultRenderer
// .getListCellRendererComponent(list, value, index, isSelected,
// cellHasFocus);
if (value != null) {
Path p = value.toPath();
System.out.println(p.getParent());
String language = value.getName().trim().replace(".srt", "");
language = language.substring(language.lastIndexOf(".") + 1,
language.length());
// System.out.println(language.length());
if (language.length() == 3) {
renderer.setText(language);
} else {
renderer.setText("Subtitulo " + (index + 1));
}
}
return renderer;
}
}
UPDATED: Here is an example that reproduce the problem
Ok, here is SSCCE code. Doing the example i noticed that when JLabel es in the same line of JCombobox reproduce the same problem but when is in other line doesn't happen.
public class Example extends JFrame {
private JPanel contentPane;
private JLabel lblNewLabel;
private JComboBox<String> comboBox;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Example frame = new Example();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Example() {
initGUI();
}
private void initGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 428, 362);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
lblNewLabel = new JLabel("New label");
contentPane.add(lblNewLabel, BorderLayout.WEST);
Timer t = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Random r = new Random();
lblNewLabel.setText(String.valueOf(r.nextInt()));
}
});
t.start();
comboBox = new JComboBox<>();
comboBox.setRenderer(new ListCellRenderer<String>() {
#Override
public Component getListCellRendererComponent(
JList<? extends String> list, String value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel label = new JLabel("");
System.out.println("Pass");
return label;
}
});
contentPane.add(comboBox, BorderLayout.CENTER);
}
}
Related
I'm trying to use JCombobox inside the JPopupMenu, but without success, popup becomes visible when user clicks the label,
label = new JLabel();
label.addMouseListener(this);
this is the label code, with mouse listener, on mousePressed and mouseClicked events it does display and hide popup menu, inside the menu I have JPanel which contains ButtonGroup, click on buttons displays different JPanel's in the center of the panel, short exmaple of panel and popup menu code looks like this
popupPanel = new JPanel();
popupPanel.setLayout(new BorderLayout());
menu = new JPopupMenu();
menu.add(BorderLayout.CENTER, popupPanel);
menu.pack();
menu.addPopupMenuListener(this);
popup panel contains button groups as i mentioned above, when one of the buttons is clicked it displays
color_combo_panel = new JPanel();
color_combo_panel.setLayout(new GridBagLayout());
color_combo = new JComboBox<>();
color_combo.addItem(Color.RED.toString());
color_combo.addItem(Color.BLUE.toString());
color_combo.addItem(Color.CYAN.toString());
color_combo.setRenderer(new ColorRenderer());
panel containing JCombobox, problem starts from here, when I click on combo box to select the color, JPopupMenu gets closed, on the ather hand JCombobox selection does nothing, my question is, how can I force popup menu to stay visible, with mouse and popup listeners i have forced it to stay visible, but as a result I get IllegalComponentStateException, component must be shown on the screen, I found problem similar to mine, but it do not provide relevant solution, plus this behavior is submitted as a BUG here.
will much appreciate any useful advice
EDIT minimal reproducible example asked by #camickr
public class PopupTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(new Dimension(500, 500));
frame.setLayout(new GridBagLayout());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(new ColorCombo());
frame.setVisible(true);
}
static class ColorCombo extends JComboBox {
private static final long serialVersionUID = 2L;
public ColorCombo() {
setPreferredSize(new Dimension(200, 30));
}
#Override
public void updateUI() {
ComboBoxUI cui = (ComboBoxUI) UIManager.getUI(this);
if (cui instanceof MetalComboBoxUI) {
cui = new MetalBrushComboBoxUI();
} else {
cui = new BasicBrushComboboxUI();
}
setUI(cui);
}
class MetalBrushComboBoxUI extends MetalComboBoxUI {
#Override
protected ComboPopup createPopup() {
return new ColorPopup(comboBox);
}
}
class BasicBrushComboboxUI extends BasicComboBoxUI {
#Override
protected ComboPopup createPopup() {
return new ColorPopup(comboBox);
}
}
class ColorPopup extends MouseAdapter implements ComboPopup, ActionListener {
private JList list = new JList();
private JComboBox comboBox;
private JPopupMenu popupMenu;
private JPanel container, first_color_panel;
public ColorPopup(JComboBox comboBox) {
this.comboBox = comboBox;
container = new JPanel();
container.setLayout(new BorderLayout());
JToggleButton first_button = new JToggleButton();
first_button.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, false));
first_button.setPreferredSize(new Dimension(20, 20));
first_button.setBackground(Color.WHITE);
first_button.addActionListener(this);
first_button.setActionCommand("color1");
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(first_button);
JPanel northPanel = new JPanel();
northPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
northPanel.add(first_button);
first_color_panel = new JPanel();
first_color_panel.setLayout(new GridBagLayout());
JComboBox<String> color_combo = new JComboBox<>();
color_combo.setPreferredSize(new Dimension(120, 30));
for (String color : getColors().keySet())
color_combo.addItem(color);
color_combo.setRenderer(new ColorRenderer());
color_combo.addActionListener(this);
color_combo.setActionCommand("color1_ground");
first_color_panel.add(color_combo);
container.add(northPanel, BorderLayout.NORTH);
popupMenu = new JPopupMenu();
popupMenu.add(BorderLayout.CENTER, container);
}
#Override
public void actionPerformed(ActionEvent e) {
boolean isSet = container.getComponents().length == 2;
if ("color1".equals(e.getActionCommand())) {
if (isSet)
container.remove(1);
container.add(first_color_panel, BorderLayout.CENTER);
}
container.revalidate();
popupMenu.repaint();
}
#Override
public void show() {
this.container.setPreferredSize(new Dimension(this.comboBox.getWidth(), 100));
popupMenu.add(BorderLayout.CENTER, container);
popupMenu.pack();
popupMenu.show(this.comboBox, 0, this.comboBox.getHeight());
}
#Override
public void hide() {
popupMenu.setVisible(false);
}
#Override
public boolean isVisible() {
return popupMenu.isVisible();
}
#Override
public JList getList() {
return list;
}
#Override
public MouseListener getMouseListener() {
return this;
}
#Override
public MouseMotionListener getMouseMotionListener() {
return this;
}
#Override
public KeyListener getKeyListener() {
return null;
}
#Override
public void uninstallingUI() {
}
#Override
public void mouseClicked(MouseEvent e) {
comboBox.requestFocus();
toggle();
}
private void toggle() {
if (isVisible()) {
hide();
} else {
show();
}
}
private Map<String, Color> getColors() {
Map<String, Color> colors = new HashMap<>();
colors.put("Red", Color.RED);
colors.put("blue", Color.BLUE);
colors.put("green", Color.GREEN);
colors.put("Yellow", Color.YELLOW);
return colors;
}
class ColorRenderer extends JPanel implements ListCellRenderer<String> {
#Override
public Component getListCellRendererComponent(JList<? extends String> list, String value, int index, boolean isSelected, boolean cellHasFocus) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout(3, 3));
panel.setBorder(BorderFactory.createCompoundBorder(getBorder(),
BorderFactory.createEmptyBorder(0, 0, 3, 0)));
JLabel label = new JLabel();
label.setOpaque(true);
label.setPreferredSize(new Dimension(20, label.getHeight()));
label.setBackground(getColors().get(value));
JLabel text = new JLabel();
text.setText(value);
panel.add(label, BorderLayout.WEST);
panel.add(text, BorderLayout.CENTER);
return panel;
}
}
}
}}
I have written the following code to make a JTable. I am practicing to edit value on row by setting JButton and JTextField but the output of JButton and JTextField is unseen.
public class quotingtable extends javax.swing.JFrame {
DefaultTableModel model;
JTable table;
String col[] = { "Symbol", "Name", "LastPrice" };
JButton button = new JButton("Set Value at 1, 1");
JTextField text = new JTextField(20);
JPanel panel = new JPanel();
public void start() {
model = new DefaultTableModel(col,50);
table = new JTable(model) {
#Override
public boolean isCellEditable(int arg0 ,int arg1) {
return false;
}
};
panel.add(table);
panel.add(text);
panel.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String value = text.getText();
model.setValueAt(value, 1, 0);
}
});
JScrollPane pane = new JScrollPane(table);
table.setValueAt("VNM", 0, 0);
add(pane);
setSize(500, 400);
setLayout(new FlowLayout());
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String args[]) {
new quotingtable().start();
}
}
I would like to make multiple cells bold, I have arraylist with the cell names that should be bold but doesn't seem to work. My Arraylist with the cells that I want to bold is called bibNumbers, so far tried converting the arralist into array and putting the if statement into a loop and loop results into bolding variable
//edit
added example, so now id want all the 0's and 1's in the column 2 to be bold.
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class as extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JTable table;
private ArrayList<String> ShadowBibNumber;
/**
* Launch the application.
*/
public static void main(String[] args) {
as frame = new as();
frame.setVisible(true);
}
/**
* Create the frame.
*/
public as() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
ShadowBibNumber = new ArrayList<String>();
ShadowBibNumber.add("0");
ShadowBibNumber.add("1");
JLabel lblNewLabel = new JLabel("New label");
contentPane.add(lblNewLabel, BorderLayout.NORTH);
DefaultTableModel tableModel = new DefaultTableModel();
tableModel.addColumn("column 0");
tableModel.addColumn("column 1");
tableModel.addColumn("column 2");
tableModel.addColumn("column 3");
tableModel.addColumn("column 4");
new JScrollPane(table);
table = new JTable(tableModel);
table.setEnabled(false);
table.setPreferredScrollableViewportSize(new Dimension(200, 100));
JScrollPane scrollPaneForTable = new JScrollPane(table);
contentPane.add(scrollPaneForTable, BorderLayout.CENTER);
for (int i = 0; i < 20; ++i) {
tableModel
.addRow(new Object[] { i, i, i, i, i });
}
table.getColumn("column 2").setCellRenderer(new boldRenderer());
}
class boldRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component cellComponent = super.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
for (Object x: ShadowBibNumber) {
if (table.getValueAt(row, 2).equals(x)) {
cellComponent.setFont(cellComponent.getFont().deriveFont(
Font.BOLD));
} else {
cellComponent.setFont(cellComponent.getFont().deriveFont(
Font.PLAIN));
}
}
return cellComponent;
}
} }
I'm currently writing a custom ListCellRenderer for a JComboBox. To do this, I'm using a system to fetch a new renderer whenever the L&F changes, and delegate the method to this. This works nicely in all L&Fs. However, when I place this component in a panel (so I can add some more components), it works nicely in the Metal and Windows L&Fs, but the JComboBox text disappears in Motif. See screenshot and code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TextDemo extends JPanel implements ActionListener {
private static JFrame frame;
public TextDemo() {
super(new GridBagLayout());
JComboBox correct = new JComboBox(new String[]{"One", "Two", "Three"});
JComboBox alsoCorrect = new JComboBox(new String[]{"One", "Two", "Three"});
alsoCorrect.setRenderer(new MyRenderer());
JComboBox incorrect = new JComboBox(new String[]{"One", "Two", "Three"});
incorrect.setRenderer(new NotWorkingRenderer());
JButton button = new JButton("Change LnF");
button.addActionListener(this);
add(correct, getConstraints(0));
add(alsoCorrect, getConstraints(1));
add(incorrect, getConstraints(2));
add(button, getConstraints(3));
}
private GridBagConstraints getConstraints(int y) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0; c.gridy = y;
c.insets = new Insets(4,8,4,8);
c.weightx = 1.0; c.weighty = 1.0;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.FIRST_LINE_START;
return c;
}
#Override
public void actionPerformed(ActionEvent ev) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
SwingUtilities.updateComponentTreeUI(frame);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static void createAndShowGUI() {
frame = new JFrame("TextDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TextDemo());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
class MyRenderer implements ListCellRenderer {
protected static ListCellRenderer delegate;
static {
refreshRenderers();
UIManager.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("lookAndFeel")) {
refreshRenderers();
}
}
});
}
protected static void refreshRenderers() {
delegate = new JComboBox().getRenderer();
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
return delegate.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);
}
}
class NotWorkingRenderer extends MyRenderer {
private JPanel panel = new JPanel();
public NotWorkingRenderer() {
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
c.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
panel.removeAll();
panel.add(c);
return panel;
}
}
Any help on understanding why this happens would be greatly appreciated!
not an answer,
but see whats happens, with JPanel as renderers JComponents for JComboBox
are you sure that JPanel with String value is proper way, please whats goal,
is there the same effect with default JLabel, (J)Component instead of JPanel
from code
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class TextDemo extends JPanel implements ActionListener {
private static JFrame frame;
public TextDemo() {
super(new GridBagLayout());
JComboBox correct = new JComboBox(new String[]{"One", "Two", "Three"});
JComboBox alsoCorrect = new JComboBox(new String[]{"One", "Two", "Three"});
alsoCorrect.setRenderer(new MyRenderer());
JComboBox incorrect = new JComboBox(new String[]{"One", "Two", "Three"});
incorrect.setRenderer(new NotWorkingRenderer());
JButton button = new JButton("Change LnF");
button.addActionListener(this);
add(incorrect, getConstraints(0));
add(correct, getConstraints(1));
add(alsoCorrect, getConstraints(2));
add(button, getConstraints(3));
}
private GridBagConstraints getConstraints(int y) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = y;
c.insets = new Insets(4, 8, 4, 8);
c.weightx = 1.0;
c.weighty = 1.0;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.FIRST_LINE_START;
return c;
}
#Override
public void actionPerformed(ActionEvent ev) {
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
SwingUtilities.updateComponentTreeUI(frame);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static void createAndShowGUI() {
frame = new JFrame("TextDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TextDemo());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
//SwingUtilities.updateComponentTreeUI(frame);
} catch (Exception ex) {
ex.printStackTrace();
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
class MyRenderer implements ListCellRenderer {
protected static ListCellRenderer delegate;
static {
refreshRenderers();
UIManager.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("lookAndFeel")) {
refreshRenderers();
}
}
});
}
protected static void refreshRenderers() {
delegate = new JComboBox().getRenderer();
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
return delegate.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);
}
}
class NotWorkingRenderer extends MyRenderer {
private JPanel panel = new JPanel();
public NotWorkingRenderer() {
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
c.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
panel.add(c);
return panel;
}
}
EDIT_1st.
all Standard L&F excluding ModifL&F showing that properly
one step forward ???, code line incorrect.setEditable(true); generating
I'm don't know proper way for ModifL&F and non_editable JComboBox
EDIT_2nd.
I'm blind class NotWorkingRenderer extends MyRenderer {, pip... pip... pip...
phaaa I'm participated on never ever to add / remove / modify a JComponent in Xxx(Xxx)Renderer, but is about if is possible or not,
class NotWorkingRenderer extends BasicComboBoxRenderer {
private JPanel panel = new JPanel();
public NotWorkingRenderer() {
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
//panel.setOpaque(false);
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
JLabel c = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
c.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
panel.removeAll();
panel.add(c);
panel.revalidate();
panel.repaint();
return panel;
}
}
You are returning the panel instead of c
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
c.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
panel.removeAll();
panel.add(c);
return c;
I have JComboBox with 2 columns and I have JButton. When I click the JButton, I need to get the result of the JComboBox selected value from first column and seconds column separately...
How do I this?
Also: how do I set the header of that JComboBox ?
The Code:
public class Combo extends JFrame implements ActionListener{
private JComboBox combo = new JComboBox();
private JButton button = new JButton();
public Combo() {
setLayout(new FlowLayout());
combo.setRenderer(new render());
add(combo);
combo.addItem(new String[] {"1","bbb"});
combo.addItem(new String[] {"2","ff"});
combo.addItem(new String[] {"3","gg"});
combo.addItem(new String[] {"4","ee"});
add(button);
button.addActionListener(this);
pack();
}
public static void main(String[]args){
new Combo().setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button){
System.out.println(combo.getSelectedItem());
}
}
}
class render extends JPanel implements ListCellRenderer{
private JLabel label1 = new JLabel();
private JLabel label2 = new JLabel();
private JLabel label3 = new JLabel();
private JLabel label4 = new JLabel();
private JLabel label5 = new JLabel();
public render() {
setLayout(new GridLayout(2,5));
add(label1);
add(label2);
}
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
String[] values = (String[]) value;
label1.setText(values[0]);
label2.setText(values[1]);
if(index ==0){
label1.setForeground(Color.red);
label2.setForeground(Color.red);
}else{
label1.setForeground(Color.white);
label2.setForeground(Color.white);
}
return this;
}
}
Thanks.
Your items are arrays of strings, so you can print the selected item as follows:
System.out.println(Arrays.toString((String[])combo.getSelectedItem()));
EDIT:
String[] selectedItem = (String[])combo.getSelectedItem();
for (int i = 0; i < selectedItem.length; i++){
System.out.println(String.format("item %s = %s", i, selectedItem[i]));
}
Or shortly if all you need is the first item - (String[])combo.getSelectedItem())[0].
To display the first value of the selected element, you could use:
System.out.println(((String[])combo.getSelectedItem())[0]);
I think this could be easier than the previous answers:
(String) comboBox.getSelectedItem();