Adapt JComboxBox maximumRowCount to JFrame or Screen Size - java

Everything is in the title.
In my application, depending on a selection made by the user I fill up a combobox with a list which can sometime be small (1 element) sometimes be large (150 elements).
What I would like is not to have a fixed height set at startup to a given value but to set the maximumRowCount to the height of my JFrame or to the height of my screen and I don't know how to determine the number of rows that would match my application height or my screen height. This should be dynamical (at runtime) so when I change the combobox font size the maximumRowCount also adapts itself.
Can anyone help me?

So you need to figure out how big each row in the drop-down list is. To do this, the easy way is to create a cell renderer, populate it, and ask it for its preferred height.
final DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
dlcr.setText("one of my combo items");
int numRows = (int)( (1.0f * frame.getHeight()) / dlcr.getPreferredSize().height );
setMaximumRowCount(numRows);
Note that I used frame.getHeight() here, but at least in some look-and-feels, the drop-down list starts below the combo box, so you'd have to make some adjustment for that. And there are ways to get the size of a screen, too, such as those in http://docs.oracle.com/javase/6/docs/api/java/awt/Toolkit.html.

Below is a code snippet which sets the rowCount dynamically
The basic steps
get the pref size of the rendering component
get the location of the combo relative to the context you want (the example takes the screen) and the available space below
calculate the number of rows which fit into the available space
do all this in a PopupMenuListener to be really dynamical
The code (which is obviously not production quality, just to give you something to play with :-)
final JComboBox box = new JComboBox(new Object[] {1, 2, 3, 4, 5, 6, 6, 34,3,3});
PopupMenuListener l = new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
int pref = getRowHeight(box);
int available = getAvailableScreenHeightBelow(box);
int count = available / pref;
box.setMaximumRowCount(count);
}
private int getRowHeight(final JComboBox box) {
// note: here we assume the rendering comp's pref is the same for all rows
ComboPopup popup = (ComboPopup) box.getAccessibleContext().getAccessibleChild(0);
ListCellRenderer renderer = box.getRenderer();
Component comp = renderer.getListCellRendererComponent(popup.getList(), 1, 0, false, false);
int pref = comp.getPreferredSize().height;
return pref;
}
private int getAvailableScreenHeightBelow(final JComboBox box) {
// note: this is crude - f.i. doesn't take taskbar into account
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
Point location = box.getLocationOnScreen();
location.y += box.getHeight();
int available = screen.height - location.y;
return available;
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
};
box.addPopupMenuListener(l);

Related

How do you embed a resizable JPanel inside of a JTextPane?

There are many questions of the converse, inserting a JTextPane into a JPanel. This is not my question. I need to be able to insert a custom JPanel (with drag and drop, drag, and mouse click listeners) into a JTextPane, which is then put into a JScrollPane, and finally put into a JFrame for displaying. The reason is because I need to have an image with support for resizing by dragging it within a chat client, which is itself primarily text.
Conveniently enough, there is a relevant method in JTextPane: insertComponent(Component c), but whenever I use it, my components end up being squished to exactly one line of text worth of space (even though they report having a larger size). This is perfect for plain buttons, but if I need anything larger, I'm out of luck. I can insert images by themselves just fine, with ImageIcons, but images wrapped inside a JPanel don't work at all (plus I can't add any listeners to ImageIcons, since they're not GUI elements; overriding one isn't an option).
Whenever a user drags an image into the chat client, this bit of code inserts the custom JPanel:
private void sendImage(BufferedImage im, int cl) throws IOException {
if(output == null) return;
//Send the image itself over to your friend
byte[] toSend = toBytes(im, cl);
sendString(nickname.hashCode() + "image"); //Header for image
output.writeInt(toSend.length); //Tells how many bytes to read.
output.write(toSend);
//Let the user know that the image was sent
float linmb = (float)(toSend.length / 1048576.0); //Size of file sent
addText("\n" + nickname + " sent an image! (" + linmb + " MB)\n", Color.RED.darker());
//Show the image itself
DraggerPanel d = new DraggerPanel(im, true);
text.insertComponent(d);
d.repaint();
//Spacer
addText("\n");
}
This is the source for DraggerPanel, the custom JPanel that holds an image:
public class DraggerPanel extends JPanel {
private BufferedImage image; //The image we're drawing
private Point startingPoint = null; //Starting point for resizing
private boolean first = true; //Is this the first drag?
private boolean lockedDrag; //If true, then lock x and y to be proportionally dragged.
public DraggerPanel(BufferedImage image, boolean lockedDrag) {
super();
this.image = image;
this.lockedDrag = lockedDrag;
//The listener for dragging events.
addMouseMotionListener(new MouseMotionListener() {
private int inWidth = 0, inHeight = 0; //Initial height and width values
private double ratio = 0; //Ratio of height to width for locked drag.
public void mouseDragged(MouseEvent m) {
if (first) { //If we're first, record initial position.
startingPoint = m.getPoint();
first = false;
inWidth = getWidth();
inHeight = getHeight();
ratio = (double)inHeight / inWidth;
} else { //Otherwise, change the size of the window.
if (!lockedDrag) {
int w = (int)startingPoint.getX() - m.getX();
int h = (int)startingPoint.getY() - m.getY();
setSize(Math.abs(inWidth - w), Math.abs(inHeight - h));
} else {
int w = (int)startingPoint.getX() - m.getX();
int h = (int)((double)ratio * w);
setSize(Math.abs(inWidth - w), Math.abs(inHeight - h));
}
}
repaint();
}
public void mouseMoved(MouseEvent m){
}
});
//Lets us know when you're not dragging anymore.
addMouseListener(new MouseAdapter(){public void mouseReleased(MouseEvent m){first = true;}});
//Set appropriate size.
if(image != null) setSize(image.getWidth(), image.getHeight());
else setSize(200,200);
//We're live, baby.
setVisible(true);
}
public void paint(Graphics g) {
if (image == null) super.paint(g);
else g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
}
Update 1: I followed #camickr 's advice, and updated the DraggerPanel to use setPreferredSize instead of setSize, as well as overrode paintComponent() instead of paint(). Now, the image has the proper height, but is stretched to the width of the JTextPane (which seems like what it was doing before). Furthermore, resizing doesn't seem to matter- the image doesn't change its size at all. Mouse events are definitely going through, but not affecting the size. It seems as though the original problem isn't fully resolved, since the JPanel's size isn't what I need it to be, and the solution to that will also lead to a solution to the resizing issue.
Update 2: I did it! I finally did it. To the future time travelers who have this issue, I basically yelled at the JTextPane by not only using setSize() in my overridden JPanel, but also setPreferredSize() and setMaximumSize(). The preferred one works well with height, and the maximum sets the width (God knows why). Thanks for your tips, #camickr!
my components end up being squished to exactly one line of text worth of space (even though they report having a larger size).
I would guess the size is not important.
I would think you need to override the getPreferredSize() method of your DraggerPanel to return the preferred size of the panel so the text pane can display the panel.
Also, custom painting is done by overriding the paintComponent(...) method NOT the paint() method.

Android's LinearLayout equivalent in Swing

I have seen this thread which asked the exact same question I have now, but find the answers a bit unsatisfactory:
Android's LinearLayout for Swing
I created a class WeightedPanel like so:
public class WeightedPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 6844740568601141924L;
private boolean mVertical;
private double mLastWeight = 1;
private GridBagConstraints mConstraints;
private int mLastGrid = 0;
public WeightedPanel(boolean vertical) {
mVertical = vertical;
mConstraints = new GridBagConstraints();
setLayout(new GridBagLayout());
}
#Override
public Component add(Component comp) {
return add(comp, mLastWeight);
}
public Component add(Component comp, double weight) {
if (mVertical) {
mConstraints.weighty = weight;
mConstraints.weightx = 1;
mConstraints.gridy = mLastGrid;
mConstraints.gridx = 0;
} else {
mConstraints.weightx = weight;
mConstraints.weighty = 1;
mConstraints.gridx = mLastGrid;
mConstraints.gridy = 0;
}
mConstraints.fill = GridBagConstraints.BOTH;
add(comp, mConstraints);
mLastWeight = weight;
mLastGrid += weight;
return comp;
}
public Component add(Component comp, int weight) {
return add(comp, (double) weight);
}
}
This kind of works, but I have two problems with it:
1) In my application, I have a login screen:
#Override
protected void addComponents(WeightedPanel jPanel) {
mUpdateListener = new UpdateListener() {
#Override
public void onUpdate() {
LoginFrame.this.onUpdate();
}
};
WeightedPanel panel = getUserPanel();
jPanel.add(panel);
panel = getPasswordPanel();
jPanel.add(panel);
mLoginButton = getLoginButton();
jPanel.add(mLoginButton);
}
private WeightedPanel getPasswordPanel() {
WeightedPanel result = new WeightedPanel(false);
JLabel label = new JLabel("Password");
result.add(label);
mPasswordField = new PasswordField(mUpdateListener);
result.add(mPasswordField);
return result;
}
private WeightedPanel getUserPanel() {
WeightedPanel result = new WeightedPanel(false);
JLabel label = new JLabel("User");
result.add(label);
mUserTextField = new TextField(mUpdateListener);
result.add(mUserTextField);
return result;
}
which in practice looks like this:
Click to view
Why aren't the labels and text fields all the same size here? I figure it's got something to do with the fact that "Password" is a longer string than "User", but that's obviously not what I want!
2) My second problem is this. I have another screen like so:
#Override
protected void addComponents(WeightedPanel jPanel) {
WeightedPanel scrollPanePanel = getOrdersScrollPane();
jPanel.add(scrollPanePanel);
WeightedPanel buttonPanel = getButtonPanel();
jPanel.add(buttonPanel);
}
private WeightedPanel getOrdersScrollPane() {
WeightedPanel result = new WeightedPanel(true);
JPanel filterPanel = getFilterPanel();
result.add(filterPanel, 1);
mTableModel = new OrdersTableModel();
mTable = new JTable(mTableModel);
mTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
mTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent arg0) {
checkEnabled();
}
});
JScrollPane scrollPane = new JScrollPane(mTable);
result.add(scrollPane, 40);
return result;
}
It really doesn't look bad in practice:
Click to view
But have a look at the getOrdersScrollPane() function. The call to functions result.add(filterPanel, 1); and result.add(scrollPane, 50); say that the proportion between the filter panel and the scroll pane should be 1:50, but looking at the scroll pane, it's definitely not 50 times the size of the filter panel. Obviously, I am exaggerating to make my point, I don't really want a proportion of 1:50; it just strikes me that it makes no difference whether I do result.add(scrollPane, 10); or result.add(scrollPane, 50);
Both questions stem from an incorrect understanding of GridBagLayout. A bit more reading and experimenting should help) To answer the question at hand:
1) The problem here is that you want a single GridBagLayout, but instead are adding 2 independent panels.
The result: The columns in the top grid bag are independent of the columns in the bottom grid bag.
To rectify this, there are 2 things you can try:
Add both labels and both text fields to a single GridBag panel. That way the columns will align.
Make a minimum and preferred size for the labels so that their width matches and set their weightx to 0 (and weightx of text fields non-zero). That way you are making the GridBags allocate the same amount of space for the labels and text fields.
The first method is preferred, but not always possible. The second method is hacky and will likely break as soon as you change the label string, a user set a different default font etc, etc.
2) Here you are misunderstanding what weighty does.
It does not make your components of the specified proportion. That should be clear enough since you can mix 0 and non-0 weight components in a single layout.
What it does, is it allocates the preferred (or minimum) sizes for components, and distributes the remaining space in that proportion. Which means if you make your panel 100 pixels higher by resizing the window, 2 will go to the top panel adding spacing, and 98 will go to the table.
What you likely wanted is to make the weighty of the top filter 0 (so that there is no awkward spacings in large windows) and control its actual height with setPreferred and setMinimum size (or by setting those on the embedded components).
EDIT
As docs for Linear Layout state, to achieve a fixed proportion of sizes of components (the initial problem), one has to set their preferred sizes to 0, and then set weights (then all space is remaining space, and is distributed according to weights only). This also works for the GridBag variant.

Given two label fields inside an HorizontalFieldManager, how should I do to display the full text from second label without wrapping it?

I have an HorizontalFieldManager with two labels inside.
The left label shows a description, and the right one shows
a money amount.
For me, it's more important to show the full text of the
second label. Problem is that if the first label is too long,
the second label will be wrapped. I want to avoid that, so
text from second label always is displayed. I also need to avoid
the wrapping over first label in that case, so text from that label
is trimmed and filled with dots.
This is how the HorizontalFieldManager looks:
And this is what I need to get:
How should I do that?
Thanks in advance!
If you create your LabelField with the LabelField.ELLIPSIS flag, it will truncate the field with . characters. I would recommend that you use a custom Manager subclass (instead of HorizontalFieldManager) to decide what the proper width of your two LabelFields should be. You can do this by asking what the proper width is of the dollar amount, given the current font.
Try this example:
public class LabelAlignScreen extends MainScreen {
private LabelField description;
private LabelField balance;
private static final int MARGIN = 8; // used for x and y
public LabelAlignScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
Manager row = new RowManager(Manager.USE_ALL_WIDTH);
description = new LabelField("This is a very looooooooooong description",
LabelField.ELLIPSIS);
row.add(description);
balance = new LabelField("1,500,000,000 USD");
row.add(balance);
add(row);
}
private class RowManager extends Manager {
public RowManager(long flags) {
super(flags);
}
protected void sublayout(int width, int height) {
// first, determine how much space the balance field needs
int balanceWidth = balance.getFont().getAdvance(balance.getText());
// description field gets leftover width,
// minus a margin at left, center and right
int descriptionWidth = width - balanceWidth - 3 * MARGIN;
setPositionChild(description, MARGIN, MARGIN);
layoutChild(description, descriptionWidth, description.getPreferredHeight());
setPositionChild(balance, MARGIN + descriptionWidth + MARGIN, MARGIN);
layoutChild(balance, balanceWidth, balance.getPreferredHeight());
setExtent(width, getPreferredHeight());
}
public int getPreferredHeight() {
return Math.max(balance.getPreferredHeight(), description.getPreferredHeight()) + 2 * MARGIN;
}
public int getPreferredWidth() {
return Display.getWidth();
}
}
}
Note: you didn't specify whether the dollar/balance field should be a fixed width, or always just barely enough to fit the text. I assumed that it should just barely fit the text, as I think that makes for a better layout in most cases. Also, my code above uses a hardcoded MARGIN value for the space around all the fields. You can adjust that if you like.
Results
See that example :
class Test {
public String StringShorter(String field, int maxsize) {
//create a function that process the String you want to put in your field
StringBuilder strb=new StringBuilder();
// lets say you want your field to not more than 10 characters
if(field.length()>=maxsize) {
strb.append(field.substring(0,maxsize));
strb.append("...");
}
return strb.toString();
}
public static void main(String[] args) {
Test sl=new Test();
System.out.println(sl.StringShorter("sdadasfdfsdfsdfsdfdsffdfs", 10));
// define the maximum characters here it is defined to be maximum 10 characters
}
}
the output would be :
sdadasfdfs...

How to implement freeze column in GXT 3.x?

How can frozen columns be implemented in GXT 3.x (from Sencha)? Ext-JS, another product from Sencha seems to implement this, but I can't see where the Java based GXT implement the same thing:
http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/locking-grid.html
The basic idea is that you need two different scrolling containers, one with the fixed column(s), one with the scrolling columns. Each of these need to be in a distinct viewport, so the standard Grid/GridView doesn't work well with this - they make assumptions about how scrolling should behave, so simply subclassing one or both is likely to be fairly involved.
Instead, you can build two grids, one for the locked columns, one for the scrolling ones. Each can deal with their own ColumnConfig classes, to draw headers and rows, and will be linked to the same ListStore to ensure their data is in sync - changes in the store will be passed along to both listening grids.
To get the full effect, some additional wiring will be needed:
Linking scrolling. Listen to the BodyScrollEvent from each Grid, and scroll the other to the same place (changing only top, not left, since you don't want one to control the other).
Sizing is the second big piece - both grids need their scrollable height to be the same, but the horizontal scrolling one needs a buffer on the bottom when it is actually showing that scrollbar. Usually the Grid is told to size based on its parent's instructions, though sometimes you directly size the Grid - in this case, this step is not needed, just size the two grids slightly differently. Otherwise, you'll need to structure the layout to properly configure this.
Finally, the locked column needs its vertical scrollbar to be hidden away - the user has no need to see two vertical scrollbars.
This covers the basic use case, but doesn't deal with things like alternate GridView implementations - GroupingView and subclasses will need to link expanding (and to hide the group headings so they don't appear twice, plus deal with the fact that the group row shouldn't get split when the second half scrolls sideways), TreeGridView and TreeGrid will need to link expanding nodes and hide the tree +/- icons from the second grid.
Here's this basic set of modifications applied to the basic grid example at http://www.sencha.com/examples/#ExamplePlace:basicgrid. To help avoid confusing the issue, I've deleted a number of other features in that grid such as tooltips and changing the selection model:
public class GridExample implements IsWidget, EntryPoint {
private static final StockProperties props = GWT.create(StockProperties.class);
private ContentPanel root;
#Override
public Widget asWidget() {
if (root == null) {
final NumberFormat number = NumberFormat.getFormat("0.00");
ColumnConfig<Stock, String> nameCol = new ColumnConfig<Stock, String>(props.name(), 50, SafeHtmlUtils.fromTrustedString("<b>Company</b>"));
ColumnConfig<Stock, String> symbolCol = new ColumnConfig<Stock, String>(props.symbol(), 100, "Symbol");
ColumnConfig<Stock, Double> lastCol = new ColumnConfig<Stock, Double>(props.last(), 75, "Last");
ColumnConfig<Stock, Double> changeCol = new ColumnConfig<Stock, Double>(props.change(), 100, "Change");
changeCol.setCell(new AbstractCell<Double>() {
#Override
public void render(Context context, Double value, SafeHtmlBuilder sb) {
String style = "style='color: " + (value < 0 ? "red" : "green") + "'";
String v = number.format(value);
sb.appendHtmlConstant("<span " + style + " qtitle='Change' qtip='" + v + "'>" + v + "</span>");
}
});
ColumnConfig<Stock, Date> lastTransCol = new ColumnConfig<Stock, Date>(props.lastTrans(), 100, "Last Updated");
lastTransCol.setCell(new DateCell(DateTimeFormat.getFormat("MM/dd/yyyy")));
List<ColumnConfig<Stock, ?>> l = new ArrayList<ColumnConfig<Stock, ?>>();
//Remove name from main set of columns
// l.add(nameCol);
l.add(symbolCol);
l.add(lastCol);
l.add(changeCol);
l.add(lastTransCol);
//create two column models, one for the locked section
ColumnModel<Stock> lockedCm = new ColumnModel<Stock>(Collections.<ColumnConfig<Stock, ?>>singletonList(nameCol));
ColumnModel<Stock> cm = new ColumnModel<Stock>(l);
ListStore<Stock> store = new ListStore<Stock>(props.key());
store.addAll(TestData.getStocks());
root = new ContentPanel();
root.setHeadingText("Locked Grid Sample");
root.setPixelSize(600, 300);
final Resizable resizable = new Resizable(root, Dir.E, Dir.SE, Dir.S);
root.addExpandHandler(new ExpandHandler() {
#Override
public void onExpand(ExpandEvent event) {
resizable.setEnabled(true);
}
});
root.addCollapseHandler(new CollapseHandler() {
#Override
public void onCollapse(CollapseEvent event) {
resizable.setEnabled(false);
}
});
//locked grid
final Grid<Stock> lockedGrid = new Grid<Stock>(store, lockedCm) {
#Override
protected Size adjustSize(Size size) {
//this is a tricky part - convince the grid to draw just slightly too wide
//and so push the scrollbar out of sight
return new Size(size.getWidth() + XDOM.getScrollBarWidth() - 1, size.getHeight());
}
};
lockedGrid.setView(new GridView<Stock>(){{
this.scrollOffset=0;
}});
//require columns to always fit, preventing scrollbar
lockedGrid.getView().setForceFit(true);
//main grid, with horiz scrollbar
final Grid<Stock> grid = new Grid<Stock>(store, cm);
//don't want this feature, want to encourage horizontal scrollbars
// grid.getView().setAutoExpandColumn(nameCol);
grid.getView().setStripeRows(true);
grid.getView().setColumnLines(true);
grid.setBorders(false);
grid.setColumnReordering(true);
grid.setStateful(true);
grid.setStateId("gridExample");
//link scrolling
lockedGrid.addBodyScrollHandler(new BodyScrollHandler() {
#Override
public void onBodyScroll(BodyScrollEvent event) {
grid.getView().getScroller().scrollTo(ScrollDirection.TOP, event.getScrollTop());
}
});
grid.addBodyScrollHandler(new BodyScrollHandler() {
#Override
public void onBodyScroll(BodyScrollEvent event) {
lockedGrid.getView().getScroller().scrollTo(ScrollDirection.TOP, event.getScrollTop());
}
});
HorizontalLayoutContainer gridWrapper = new HorizontalLayoutContainer();
root.setWidget(gridWrapper);
//add locked column, only 300px wide (in this example, use layouts to change how this works
HorizontalLayoutData lockedColumnLayoutData = new HorizontalLayoutData(300, 1.0);
//this is optional - without this, you get a little offset issue at the very bottom of the non-locked grid
lockedColumnLayoutData.setMargins(new Margins(0, 0, XDOM.getScrollBarWidth(), 0));
gridWrapper.add(lockedGrid, lockedColumnLayoutData);
//add non-locked section, taking up all remaining width
gridWrapper.add(grid, new HorizontalLayoutData(1.0, 1.0));
}
return root;
}
#Override
public void onModuleLoad() {
RootPanel.get().add(asWidget());
}
}
There are a handful of issues (no line between locked and unlocked column, locked column header menu context icon is slightly out of place), but it covers most of the details without much hassle, and leaves almost all of it open to configuration - want the lock at the end? Just move the modifications around - want more than one locked column? just add more to the lockedCm.
That functionality is not implemented in GXT, but there is an user called The_Jackal who made a workaround for this problem in the Sencha Forum - Thread. I haven't tried yet, but I hope it can help you.
GXT - Freeze grid workaround Download

How to set dialog's width relative to the width of its title?

I have a JDialog with just a few components inside it. I want to make the dialog as small as possible. Currently I am using pack(). This has the unintended effect of reducing the dialog's width so much that the title is no longer completely in view. I want the dialog's width to always be great enough such that the title is always completely in view.
I am using swing. I realize that the title bar appearance/font is determined by the OS. I would prefer to stick with swing so at the moment i am planning on calculating the title string width based on the font of a JLabel. Then I will set the minimum width of one of my components equal to that.
Is there any better way to pack a JDialog while keeping its title visible?
public static void adjustWidthForTitle(JDialog dialog)
{
// make sure that the dialog is not smaller than its title
// this is not an ideal method, but I can't figure out a better one
Font defaultFont = UIManager.getDefaults().getFont("Label.font");
int titleStringWidth = SwingUtilities.computeStringWidth(new JLabel().getFontMetrics(defaultFont),
dialog.getTitle());
// account for titlebar button widths. (estimated)
titleStringWidth += 110;
// set minimum width
Dimension currentPreferred = dialog.getPreferredSize();
// +10 accounts for the three dots that are appended when the title is too long
if(currentPreferred.getWidth() + 10 <= titleStringWidth)
{
dialog.setPreferredSize(new Dimension(titleStringWidth, (int) currentPreferred.getHeight()));
}
}
EDIT:
after reading trashgod's post in the link, I adjusted my solution to override the getPreferredSize method. I think this way is better than my previous static method. Using the static method, I had to adjust it in a pack() sandwich. pack(),adjust(),pack(). This wasy doesn't require special consideration with pack().
JDialog dialog = new JDialog()
{
#Override
public Dimension getPreferredSize()
{
Dimension retVal = super.getPreferredSize();
String title = this.getTitle();
if(title != null)
{
Font defaultFont = UIManager.getDefaults().getFont("Label.font");
int titleStringWidth = SwingUtilities.computeStringWidth(new JLabel().getFontMetrics(defaultFont),
title);
// account for titlebar button widths. (estimated)
titleStringWidth += 110;
// +10 accounts for the three dots that are appended when
// the title is too long
if(retVal.getWidth() + 10 <= titleStringWidth)
{
retVal = new Dimension(titleStringWidth, (int) retVal.getHeight());
}
}
return retVal;
}
};
1) Use FontMetrics to find out the width of your title
2) Add to this value a number representing the window icon and the X (close) button (you should guess that).
3) Set the dialog's width with the above value.
You can't find the exact width size you need but this is a way to make a good guess.

Categories