Set text size of JComboBox in Swing - java

I have created a combo-box in java (using Netbeans). I want to set the text size of each item in the list but don't know how to do it. (Preferably I want to use the default font style).
Any idea anyone how to do it?
Code Snippet:
private javax.swing.JComboBox ComboBox_agent = new javax.swing.JComboBox();
ComboBox_agent.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "TCP", "UDP", "Sink", "NULL" }));

Use a list cell rendering component with an appropriate font size. This example uses 20 pixels.
import java.awt.*;
import javax.swing.*;
class ShowFonts {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
GraphicsEnvironment ge = GraphicsEnvironment.
getLocalGraphicsEnvironment();
String[] fonts = ge.getAvailableFontFamilyNames();
JComboBox fontChooser = new JComboBox(fonts);
fontChooser.setRenderer(new FontCellRenderer());
JOptionPane.showMessageDialog(null, fontChooser);
});
}
}
class FontCellRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
JLabel label = (JLabel)super.getListCellRendererComponent(
list,value,index,isSelected,cellHasFocus);
Font font = new Font((String)value, Font.PLAIN, 20);
label.setFont(font);
return label;
}
}

If you created the JComboBox in Netbeans GUI editor, there is a field for "Font" that allows you to change the size.

Related

How to include a JTable and some text below the table in JOptionPane.showMessageDialog, in Java

I am trying to include a JTable in JOptionPane.showMessageDialog and adding some more text below the table. To do so, I have tried next code:
import javax.swing.JOptionPane;
import javax.swing.*;
public class TextInTable {
public static void main(String[] args) {
String[][] rowValues = {
{"1","2","3"}
};
String[] columnNames = {
"A","B", "C"
};
JTable table = new JTable(rowValues, columnNames);
JOptionPane.showMessageDialog(null, new JScrollPane(table) +"\n"+ "I need to add some text here \n" + "and here”);
}
}
However, the JTable does not show correctly if I put this code (+"\n"+ "I need to add some text here \n" + "and here”) after the table.
This is what I am trying to do:
Any idea about how to solve it? Thanks in advance.
You need to create your own JPanel the way you want it with the components you would like and then pass that panel to the JOptionPane. Below I provide a runnable demo of this. Read all the comments in code as they explain what is going on. You can delete them later if you like. Here is what it produces on Screen:
Here is the runnable code:
package joptionpanewithjtabledemo;
public class JOptionPaneWithJTableDemo {
public static void main(String[] args) {
// Application started this way to avoid the need for statics.
new JOptionPaneWithJTableDemo().startApp(args);
}
private void startApp(String[] args) {
/* Create a JDialog box to use as a parent for the JOptionPane
just in case the JOptionPane has no parent and needs to be
displyed on top of a window that has its own ON TOP property
set to true and the JOptionPane's parent property is set to
null. If this is the case then the message box will be hidden
behind it! If your JOptionPane will be displayed on an actual
parent window then use that window's variable name as parent.
You can then delete anything in code related to iDialog.
*/
javax.swing.JDialog iDialog = new javax.swing.JDialog();
iDialog.setAlwaysOnTop(true);
iDialog.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
iDialog.setLocationRelativeTo(null);
// Create a JPanel to display within the JOptionPane MessageBox //
javax.swing.JPanel panel = new javax.swing.JPanel();
// Size the Panel to what you want to hold the JTable and JLabel
panel.setPreferredSize(new java.awt.Dimension(400, 250));
panel.setLayout(new java.awt.BorderLayout()); // Set BorderLayout as the layout manager
// JTable Column Names
Object[] columnNames = {"A", "B", "C"};
// Some fictitious data for the JTable...
Object[][] data = {
{1000, 2000, 3000}, {1001, 2001, 3001}, {1002, 2002, 3002},
{1003, 2003, 3003}, {1004, 2004, 3004}, {1005, 2005, 3005},
{1006, 2006, 3006}, {1007, 2007, 3007}, {1008, 2008, 3008},
{1009, 2009, 3009}, {1010, 2010, 3010}, {1011, 2011, 3011},
};
// Declare a JTable and initialize with the table data and column names.
javax.swing.JTable table = new javax.swing.JTable(data, columnNames);
/* Align JTable Header Text to Center.
Alignment options are: Align_LEFT (2), Align_CENTER (0), Align_RIGHT (4),
Align_LEADING (10), or Align_TRAILING (11) */
int alignType = 0;
for (int i = 0; i < table.getColumnCount(); i++) {
table.getTableHeader().getColumnModel().getColumn(i)
.setHeaderRenderer(new HeaderRenderer(table, alignType));
}
// Declare a JScrollPane and place the JTable into it.
javax.swing.JScrollPane tableScrollPane = new javax.swing.JScrollPane(table);
// Ensure the ScrollPane size.
tableScrollPane.setPreferredSize(new java.awt.Dimension(400, 200));
panel.add(tableScrollPane, java.awt.BorderLayout.NORTH); // Add the scrollpane to top of panel.
/* Use basic HTML to create you message text. Gives you more
flexability towards how your message will look. */
String msg = "<html><font size='4'>I need to add some text "
+ "<font color=blue>here</font><center>and right "
+ "<font color=red>here</font>!</center></html>";
javax.swing.JLabel msgLabel = new javax.swing.JLabel(msg);
// Set the initial text alignment in the JLabel.
msgLabel.setHorizontalAlignment(javax.swing.JLabel.CENTER);
//msgLabel.setBorder(BorderFactory.createLineBorder(Color.blue, 1));
// Ensure label width and desired height.
msgLabel.setPreferredSize(new java.awt.Dimension(panel.getWidth(), 50));
panel.add(msgLabel, java.awt.BorderLayout.SOUTH); // add label to bottom of panel.
// Display The Message Box...
javax.swing.JOptionPane.showMessageDialog(iDialog, panel, "My Table Message Box",
javax.swing.JOptionPane.INFORMATION_MESSAGE);
iDialog.dispose();
}
// Inner class - A Header cell renderer class for header text alignment options.
class HeaderRenderer implements javax.swing.table.TableCellRenderer {
javax.swing.table.DefaultTableCellRenderer renderer;
int horAlignment;
HeaderRenderer(javax.swing.JTable table, int horizontalAlignment) {
horAlignment = horizontalAlignment;
renderer = (javax.swing.table.DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
}
#Override
public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int col) {
java.awt.Component c = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
javax.swing.JLabel label = (javax.swing.JLabel) c;
label.setHorizontalAlignment(horAlignment);
return label;
}
}
}

Preferred height of JPanel is lower then combined height of its children in table renderer

I have a JTable for which the renderer returns a JPanel composed of multiple JLabel instances. One of those JLabels can contain HTML used among other things to split the output over multiple lines using <br/> tags.
To show the multiple lines in the table, the renderer calls in the getTableCellRendererComponent method
table.setRowHeight(row, componentToReturn.getPreferredSize().height);
to dynamically update the row height, based on the contents. This only works correctly if componentToReturn indicates a correct preferred size.
It looks however that the getPreferredSize returns bogus values. The preferred height of the returned component is smaller than the sum of the heights of the labels inside the component.
Here is a little program illustrating this behaviour (without using a JTable)
import java.awt.*;
import javax.swing.*;
public class SwingLabelTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
LabelPanel renderer = new LabelPanel();
Component component = renderer.getComponent(false);
//asking for a bigger component will not
//update the preferred size of the returned component
component = renderer.getComponent(true);
}
});
}
private static class LabelPanel {
private final JPanel compositePanel;
private final JLabel titleLabel = new JLabel();
private final JLabel propertyLabel = new JLabel();
public LabelPanel() {
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS));
labelPanel.add(titleLabel);
labelPanel.add(propertyLabel);
compositePanel = new JPanel(new BorderLayout());
//normally it contains more components,
//but that is not needed to illustrate the problem
compositePanel.add(labelPanel, BorderLayout.CENTER);
}
public Component getComponent( boolean aMultiLineProperty ) {
titleLabel.setText("Title");
if ( aMultiLineProperty ){
propertyLabel.setText("<html>First line<br/>Property: value</html>");
} else {
propertyLabel.setText("Property: value");
}
int titleLabelHeight = titleLabel.getPreferredSize().height;
int propertyLabelHeight = propertyLabel.getPreferredSize().height;
int compositePanelHeight = compositePanel.getPreferredSize().height;
if ( compositePanelHeight < titleLabelHeight + propertyLabelHeight){
throw new RuntimeException("Preferred size of the component returned "
+ "by the renderer is incorrect");
}
return compositePanel;
}
}
}
As I am aware that the previous example is a bit far-fetched, here an example which includes a JTable
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class SwingTableTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DefaultTableModel tableModel = new DefaultTableModel(0, 1);
JTable table = new JTable(tableModel);
table.setDefaultRenderer(Object.class, new DataResultRenderer());
tableModel.addRow(new Object[]{new Object()});
tableModel.addRow(new Object[]{new Object()});
tableModel.addRow(new Object[]{new Object()});
JFrame testFrame = new JFrame("TestFrame");
testFrame.getContentPane().add(new JScrollPane(table));
testFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
testFrame.setSize(new Dimension(300, testFrame.getPreferredSize().height));
testFrame.setVisible(true);
}
});
}
private static class DataResultRenderer implements TableCellRenderer {
private final JPanel compositePanel;
private final JLabel titleLabel = new JLabel();
private final JLabel propertyLabel = new JLabel();
public DataResultRenderer() {
JPanel labelPanel = new JPanel();
labelPanel.setOpaque(false);
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS));
labelPanel.add(titleLabel);
labelPanel.add(propertyLabel);
compositePanel = new JPanel(new BorderLayout());
//normally it contains more components,
//but that is not needed to illustrate the problem
compositePanel.add(labelPanel, BorderLayout.CENTER);
}
#Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
titleLabel.setText("Title");
if ( row == 2 ){
propertyLabel.setText("<html>Single property: value</html>");
} else {
String text = "<html>";
text += "First property<br/>";
text += "Second property<br/>";
text += "Third property:value";
text += "</html>";
propertyLabel.setText(text);
}
int titleLabelHeight = titleLabel.getPreferredSize().height;
int propertyLabelHeight = propertyLabel.getPreferredSize().height;
int compositePanelHeight = compositePanel.getPreferredSize().height;
if ( compositePanelHeight < titleLabelHeight + propertyLabelHeight){
throw new RuntimeException("Preferred size of the component returned "
+ "by the renderer is incorrect");
}
table.setRowHeight(row, compositePanel.getPreferredSize().height);
return compositePanel;
}
}
}
I am looking for a way to update the row height of the table to ensure that the multi-line content is completely visible, without knowing up front how many lines each row will contain.
So either I need a solution to retrieve the correct preferred size, or my approach is completely wrong and then I need a better one.
Note that the above examples are simplified. In the real code, the "renderer" (the code responsible for creating the component) is decorated a few times. This means that the outer renderer is the only with access to the JTable, and it has no knowledge about what kind of Component the inner code returns.
Because setRowHeight() "Sets the height, in pixels, of all cells to rowHeight, revalidates, and repaints," the approach is unsound. Absent throwing an exception, profiling shows 100% CPU usage as an endless cascade of repaints tries to change the row height repeatedly. Moreover, row selection becomes unreliable.
Some alternatives include these:
Use TablePopupEditor to display multi-line content on request from a TableCellEditor.
Update an adjacent multi-line panel from a TableModelListener, as shown here.

Set the border in a JList in Java

I have a JList in Java. Whenever the user clicks on an element,
I would like to add a specific borderLine in that element.
Is that possible?
I have the following code in Java:
DefaultListModel listModel = new DefaultListModel();
listModel.addElement("element1");
listModel.addElement("element2");
listModel.addElement("element3");
list = new JList(listModel);
list.addListSelectionListener(this);
For the listener i have:
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
if (list.getSelectedIndex() == -1) {
;
} else {
CurrentIndex = list.getSelectedIndex();
//set Current's Index border, how can i do that?
}
}
}
Create a custom renderer for the list and add a Border to the item that is selected.
Read the section from the Swing tutorial on How to Use Lists for more information and examples.
You can use a custom ListCellRender. Then in the if (isSelected) just add the border.
public class MyListCellRenderer implements ListCellRenderer{
private final JLabel jlblCell = new JLabel(" ", JLabel.LEFT);
Border lineBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
Border emptyBorder = BorderFactory.createEmptyBorder(2, 2, 2, 2);
#Override
public Component getListCellRendererComponent(JList jList, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
jlblCell.setOpaque(true);
if (isSelected) {
jlblCell.setForeground(jList.getSelectionForeground());
jlblCell.setBackground(jList.getSelectionBackground());
jlblCell.setBorder(new LineBorder(Color.BLUE));
} else {
jlblCell.setForeground(jList.getForeground());
jlblCell.setBackground(jList.getBackground());
}
jlblCell.setBorder(cellHasFocus ? lineBorder : emptyBorder);
return jlblCell;
}
}
Then instantiate the render.
MyListCellRenderer renderer = new MyListCellRenderer();
JList list = new JList();
list.setCellRenderer(renderer);
The renderer will return a JLabel. So you can do anything you want to that label and that's what will appear in cell.
See ListCellRenderer javadoc

ListCellRendererComponent() method updates all the objects(elements) of JList similar to last added element

hi there i implemented a JList which contains JLabels as elements. My aim is implementing a contact list for server/client chat application. So, when a client connects to a server, JList will build to show his/her contact list.I selected to use JLabels cause they can have icons and text as well. However, i'm getting some trouble about overridden cellrenderer method. Whenever, a client gets online/offline JList updates its state and set all the items similar to the last added item. It's something like this,
this is the first time adding an offline state client into the friend list of a person;
afterwards, this is the second time adding a different client
and finally third time...
Furthermore, i remember that in tutorial it mention about JList overrides pain method and draw whole elements again and again when there is a change in the list. Well actually i'm a newbie about this rendering subject and this thing gets very annoying. Here you can see my renderer class;
RendererSample
and add an element into the model like this way in my main class
labelSetText = tempon.getNickName();
onlineStatus = tempon.isIsOnline();
model.addElement(createPanel());
and also createPanel() returns a JLabel which is like;
public static JLabel createPanel() {
JLabel panel = new JLabel();
return panel;
}
i hope that i have been clear about my problem. I have to achieve that when a contact changes his/her state or when a contact is added this action shouldn't affect the other elements. I will be very appreciate for every answers (and also if you can add brief explanation that what and why you did i will be grateful.) well thanks anyway
You should not put components such as JLabel into JList. Instead, use a model to hold the data and add a renderer to customize the presentation. See How to Use Lists for some examples.
Here is a very basic example of a renderer that adds icon:
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.*;
public class TestUserList {
public static class UserRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean hasFocus) {
if (value instanceof UserEntry) {
UserEntry user = (UserEntry) value;
JLabel label = (JLabel) super.getListCellRendererComponent(
list, user.getName(), index, isSelected, hasFocus);
if (user.isOnline())
label.setIcon(UIManager
.getIcon("OptionPane.informationIcon"));
else
label.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
return label;
}
return super.getListCellRendererComponent(list, value, index,
isSelected, hasFocus);
}
}
public TestUserList() {
JFrame frame = new JFrame("User List");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JList list = new JList();
JScrollPane scrollPane = new JScrollPane(list);
JPanel content = new JPanel(new BorderLayout());
content.add(scrollPane, BorderLayout.CENTER);
final DefaultListModel model = new DefaultListModel();
model.addElement(new UserEntry("John", true));
model.addElement(new UserEntry("Jesse", false));
list.setModel(model);
list.setCellRenderer(new UserRenderer());
frame.add(content);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public class UserEntry {
private String name;
private boolean online;
public UserEntry(String name, boolean online) {
super();
this.name = name;
this.online = online;
}
public String getName() {
return name;
}
public Boolean isOnline() {
return online;
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestUserList();
}
});
}
}

How to get tooltip text string width in Java Swing?

I have the following lines to get a tooltip text for a JList item :
JList aList=new JList(aData)
{
public String getToolTipText(MouseEvent evt) // This method is called as the cursor moves within the list.
{
String tooltipText="Some tooltip";
int tooltipWidth= ?
return tooltipText;
}
}
Inside getToolTipText(), how do I get the tooltipText width?
You can use FontMetrics to determine the size of some text.
FontMetrics metrics = graphics.getFontMetrics(font);
int adv = metrics.stringWidth(text);
http://docs.oracle.com/javase/tutorial/2d/text/measuringtext.html
To find the used font you can query the LookAndFeel you are using
UIDefaults uidefs = UIManager.getLookAndFeelDefaults();
Font font = uidefs.getFont("ToolTip.font");
System.out.println(font);
// prints: FontUIResource[family=Dialog,name=Dialog,style=plain,size=12]
To know the keys you can use ("ToolTip.font" here), you can check the documentation of the default LookAndFeels in Swing, for example Nimbus:
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/_nimbusDefaults.html#primary
I form my tooltip in html like this : "<html>first line<Br>========<Br>second line</html>", I want the separator line "=====" to match the length of the first line, so it can look nicer, ..
Consider alternatives 2 & 3, both of which require no calculation and look better than the 'row of equals signs'.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class HtmlToolTip {
HtmlToolTip() {
String attempt1 = "<html>first line 1<Br>========<Br>second line</html>";
JLabel label1 = new JLabel(attempt1);
label1.setBorder(new LineBorder(Color.BLACK));
String attempt2 = "<html><u>first line 2</u><br>second line</html>";
JLabel label2 = new JLabel(attempt2);
label2.setBorder(new LineBorder(Color.BLACK));
String attempt3 = "<html>first line 3<hr>second line</html>";
JLabel label3 = new JLabel(attempt3);
label3.setBorder(new LineBorder(Color.BLACK));
JPanel p = new JPanel(new FlowLayout(FlowLayout.LEADING,5,5));
p.add(label1);
p.add(label2);
p.add(label3);
JOptionPane.showMessageDialog(null, p);
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new HtmlToolTip();
}
});
}
}
Thanks to the answer, I figured it out, here is what I did :
UIDefaults uidefs=UIManager.getLookAndFeelDefaults();
Font font=uidefs.getFont("ToolTip.font");
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
Graphics2D g2d=ge.createGraphics(new BufferedImage(1,1,1));
FontMetrics fontMetrics=g2d.getFontMetrics();
Top_Line_Width=fontMetrics.stringWidth("Toptip text");

Categories