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;
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 am currently using a Absolute layout where I want to place a String variable to the panel (this frame is similar to a popup dialog) with horizontal alignment. Here's a snippet of my code.
JLabel label = new JLabel(loggedInAs);
label.setBounds(10, 61, 314, 23);
label.setHorizontalAlignment(SwingConstants.CENTER);
contentPane.add(label);
When I run this the text appears to start slightly to the right, however if I enter preset text to the label such as
JLabel label = new JLabel("Hello");
it will center. Is there anyway I can resolve this?
(I have also played with the miglayout but it turned out completely different when running it from my main JFrame)
An example:
Here is an example of what I mean by it being slightly to the right
I think that your problem is in use of absolute layout, since you're using hard coded numbers to place your JLabel. The label text is itself centered fine, but if you put a border around the label, you'll likely see that the label itself, not its text, is skewed to the right. The easiest solution is to let the layout managers do the lifting for you. For example, the code below creates a successfully logged in dialog that uses a combination of layout managers to achieve what it looks like you're trying to do in your image:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class LoginPanelEg extends JPanel {
private JTextField nameField = new JTextField(20);
private Action LoginAction = new LoginAction("Login");
public LoginPanelEg() {
nameField.setAction(LoginAction);
add(new JLabel("Login Name:"));
add(nameField);
add(new JButton(LoginAction));
}
private class LoginAction extends AbstractAction {
public LoginAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic); // alt-key comb
}
#Override
public void actionPerformed(ActionEvent e) {
LoginPanel loginPanel = new LoginPanel(nameField.getText());
Window win = SwingUtilities.getWindowAncestor(LoginPanelEg.this);
JDialog dialog = new JDialog(win, "Successfully Logged In", ModalityType.APPLICATION_MODAL);
dialog.add(loginPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("LoginPanelEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new LoginPanelEg());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class LoginPanel extends JPanel {
private static final int PREF_W = 350;
private static final int PREF_H = 200;
private static final String SUCCESSFULLY_LOGGED = "Successfully logged in as:";
private static final int GAP = 20;
private static final Font PROMPT_FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 14);
private static final Font NAME_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 12);
private JLabel successfullyLoggedLabel = new JLabel(SUCCESSFULLY_LOGGED, SwingConstants.CENTER);
private JLabel nameLabel = new JLabel("", SwingConstants.CENTER);
public LoginPanel() {
successfullyLoggedLabel.setFont(PROMPT_FONT);
nameLabel.setFont(NAME_FONT);
JPanel innerPanel = new JPanel(new GridBagLayout());
innerPanel.add(successfullyLoggedLabel, createGbc(0, 0));
innerPanel.add(nameLabel, createGbc(0, 1));
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(new CloseAction("Close")));
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout());
add(innerPanel, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
LoginPanel(String name) {
this();
nameLabel.setText(name);
}
public void setName(String name) {
nameLabel.setText(name);
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
return gbc;
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class CloseAction extends AbstractAction {
public CloseAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic); // alt-key comb
}
#Override
public void actionPerformed(ActionEvent e) {
Component component = (Component) e.getSource();
if (component == null) {
return;
}
Window win = SwingUtilities.getWindowAncestor(component);
if (win == null) {
return;
}
win.dispose();
}
}
}
I am making a chat application in Java. They can add friends and chat with them.
Here is my add friend JFrame idea:
I tried to google search Multi jpanel in one jscrollpane but I found nothing. I ended up with custom JTable. I want to create a custom JTable which have JLabels in different position in each slot. Users can just select a slot in JTable, then they can use the JButton below to chat with them.
Is it possible to do this in Java. Is yes, please share your idea. Thanks.
Here is a proposal. But it contains some flaws yet
Size propagation is fiexed (may be better client or server based sizing)
No event delegation to underlying Component
Performance, because heavyweight panel instances are created frequently inside paint loop
But here is how it can be done. The code is separated into parts.
A value class
Just a simple class to represent the date inside your panels for each cell.
class Value {
public final String text;
public final boolean flag;
public Value(String text, boolean flag) {
this.text = text;
this.flag = flag;
}
}
My individual panel class
The representation can be modelled within a gui editor like google's window builder. This panel makes use of the value and displays it accordingly.
public class MyPanel extends JPanel {
public MyPanel(Value v) {
JLabel lblNewLabel = new JLabel(v.text);
add(lblNewLabel);
JCheckBox chckbxSomeValue = new JCheckBox("some value");
chckbxSomeValue.setSelected(v.flag);
add(chckbxSomeValue);
}
}
A table cell renderer class
Just returns some panel instance showing up the desired values.
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
class MyPanelCellRenderer implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
return new MyPanel((Value)value); // maybe performance problem
}
}
A custom table model
import javax.swing.table.DefaultTableModel;
class MyTableModel extends DefaultTableModel {
public MyTableModel() {
super(new Object[][] {
new Object[] { 1, new Value("asdf", true) },
new Object[] { 2, new Value("qwer", false) } },
new String[] {"Id", "MyPanel" });
}
Class[] columnTypes = new Class[] { Integer.class, Value.class };
MyTableModel(Object[][] data, Object[] columnNames) {
super(data, columnNames);
}
public Class getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
}
A frame class
import java.awt.BorderLayout;
public class MyFrame {
JFrame frame;
private JTable table;
public MyFrame() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table = new JTable();
table.setModel(new MyTableModel());
table.setFillsViewportHeight(true);
table.getColumnModel()
.getColumn(1)
.setCellRenderer(new MyPanelCellRenderer());
table.setRowHeight(40); // static sizing
JScrollPane scrollPane = new JScrollPane();
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
scrollPane.setViewportView(table);
}
}
Main Function
import java.awt.EventQueue;
public class MyApp {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MyFrame window = new MyFrame();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
The final result
The panel MyPanel is created using eclipse and google's window builder
This is a completely different approach using neither a table nor a list. It uses panels as items arranged as a list inside of another panel. This solution doesn't requires any further modification to delegate any events to the underlying controls. The events are processed natively. The idea comes from this post. I have separated the logic into two parts for now.
JPanelList class
This class is a JPanel and maintains a list of such. ATM they can be added using the methods addPanel and addPanels.
public class JPanelList extends JPanel {
private static final long serialVersionUID = 1L;
private JPanel mainList;
private List<JPanel> panels = new ArrayList<JPanel>();
public JPanelList() { this(new ArrayList<JPanel>()); }
public JPanelList(List<JPanel> panels) {
setLayout(new BorderLayout());
mainList = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
mainList.add(new JPanel(), gbc);
add(new JScrollPane(mainList));
addPanels(panels);
}
public void addPanels(List<JPanel> panels) {
for (JPanel panel : panels)
addPanel(panel);
}
public void addPanel(JPanel panel) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainList.add(panel, gbc, 0);
panels.add(panel);
validate();
repaint();
}
}
JListFrame test class with main function
public class JPanelListFrame {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JPanelListFrame window = new JPanelListFrame();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public JPanelListFrame() {
frame = new JFrame();
frame.setBounds(100, 100, 210, 192);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanelList panelList = new JPanelList();
frame.getContentPane().add(panelList, BorderLayout.CENTER);
JButton btnAddMypanel = new JButton("Add MyPanel");
btnAddMypanel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// just add a MyPanel with a Value containing a
// "asdf" and a random boolean
panelList.addPanel(new MyPanel(new Value("asdf",
(int) (2 * Math.random()) % 2 == 0)));
}
});
panelList.add(btnAddMypanel, BorderLayout.SOUTH);
}
}
One drawback with this solution is that the selection mechanics are lost. When selecting elements is a key requirement maybe a JList might be more appropriate. Another thing is that the items are not rendered as they would be rendered inside a JList or JTable e.g. using fancy borders. This can be solved by somehow adding a border decorator before adding the panels into the mainList of the JPanelList.
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 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);
}
}