Remove border from JComboBox - java

Do you know any way to remove the border from a JComboBox in Java? I try the following code
public class ComboFrame extends JFrame {
public ComboFrame() {
JPanel container = new JPanel();
JComboBox cmb = new JComboBox(new String[] { "one", "two" });
cmb.setBorder(BorderFactory.createEmptyBorder());
container.add(cmb);
getContentPane().add(container);
pack();
}
}
and
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
EventQueue.invokeLater(new Runnable() {
public void run() {
new ComboFrame().setVisible(true);
}
});
}
Don't ask why would someone want to remove the border from a combobx... I guess it does not make too much sense, but this is how it's wanted, and I got really curious if it can be done. I tried several tricks, but none of them worked.
The most effective was changing the UI with
cmb.setUI(new BasicComboBoxUI());
This makes the border go away, but alters the L&F, and I need to keep the Windows L&F if possible.
Thanks.

I did a bit of research and found this bug
I tried it for myself and it does seem to affect the border. You might want to try one or both of the following code blocks for yourself.
for (int i = 0; i < combo.getComponentCount(); i++)
{
if (combo.getComponent(i) instanceof JComponent) {
((JComponent) combo.getComponent(i)).setBorder(new EmptyBorder(0, 0,0,0));
}
if (combo.getComponent(i) instanceof AbstractButton) {
((AbstractButton) combo.getComponent(i)).setBorderPainted(false);
}
}
It is important to note that at the bottom of the bug entry, you can read the following:
The JButton maintains it's own border so JComponent paintBorder() and paintComponent() has no awareness of the JComboBox border.
Good luck,
Jeach!

If you want to use the windows L&F, you can do cmd.setUI(new WindowsComboBoxUI());
If you, however, want to be able to use any L&F, you might be better off using the solution proposed by Jeach.

Related

JSplitPane not painting correcting

In my application, I have a JFrame displaying a JSplitPane, with the split being VERTICAL_SPLIT. The top is displaying a JLabel, and the bottom is displaying a JInternalFrame. Two problems are occuring.
The JLabel is displaying, but the JInternalFrame is not.
2. I have to resize the application to have the JSplitPane display at all
I believe this is both linked to an incorrect use of JSplitPane. However, I have been unable to work out what. May I please have some help with this issue?
p.s. I have run tests to make sure GUIWindow.getInsideFrame() is not returning null. The instanceof checks at the end are saying that both components in the pane exist and are of that type. Thank you very much for all your help:
protected static void newWindow(GUIFrame window) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
JInternalFrame intFrame = window.getInsideFrame();
pane.setRightComponent(intFrame);
pane.setLeftComponent(new JLabel(window.getDescription()));
synchronized(lock){
frame.remove(currentPane);
frame.add(pane);
}
synchronized(lock){
frame.revalidate();
pane.setVisible(true);
frame.repaint();
if(window instanceof ColourFrameShower) return;
currentWindow = window;
currentPane = pane;
currentFrame = intFrame;
}
if(pane.getLeftComponent() instanceof JLabel) System.out.println("JLabel exists!");
else System.out.println("JLabel does not exist!");
if(pane.getRightComponent() instanceof JInternalFrame) System.out.println("JInternalFrame exists!");
else System.out.println("JInternalFrame does not exist!");
}
});
}
EDIT: I fixed problem 2 with a call to frame.revalidate() at the start of the second synchronised(lock) block. This has been included in the code.
As I told you in comment, you simply need to use setVisible(true) on your JInternalFrame, else it will not be considered by your JSplitPane.
This a really common mistake on java swing !
I'm glad it helped you ;)
Try to set the resizeWeight: pane.setResizeWeight(0.5);

Refresh java program with Button

I am trying to make a refresh button that will essentially restart the program when ever I click the button. I don't know how I should go about doing this.
I've place the Graphical User Interface i decided to use do complete this action. Any and all help would be greatly appreciated.
package pdfView;
import javax.swing.*;
import java.awt.*;
public class View extends JFrame {
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
JButton ReFresh = new JButton("ReFresh");
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.squing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc){
}
}
public static void main(String[] args) {
View pdf = new View();
}
}
What do you mean by refresh or restart?
Do you mean:
Let the application be as it is, just update what it's showing?
Really restart the application?
Updating what the application is showing
You first need to decide what actually should cause your application to refresh. You already talked about a Button. The mechanism for activating something like a button is called Action. You can do that stuff manually, using an ActionListener, or you could extend AbstractAction, which is what I recommend. Extending AbstractAction allows you to use the same logical action something in more than one location on the UI. Look at typical applications, they offer Cut/Copy/Paste through menu, toolbar, popupmenu and keyboard shortcuts. The simplest way to achieve this in Java is using Action by extending AbstractAction.
The methods you need to call to update your application are invalidate(), validate() or repaint().
Restarting an application
So you want to run through main() again? That should actually not be required, unless you have an application that supports updating itself. Even then it can sometimes be avoided by smart usage of a ClassLoader.
Some more notes on your code
Usage by extension anti-pattern
I wouldn't extend JFrame just to display a window on the screen. Usage by extension is an anti-pattern. You don't need to extend JFrame to get a JFrame displayed on the screen and do what you want.
Referring static members
I would refer to constants via their original declaration. I.e. I'd refer to EXIT_ON_CLOSE via WindowConstants.EXIT_ON_CLOSE, not JFrame.EXIT_ON_CLOSE.
Typo
You have a typo in your UIManager.setLookAndFeel() code. Search for swing and you will see the typo.
Exception information
You might actually want to print the exception to stderr using exc.printStackTrace() instead of ignoring it completely, because when you have a typo in the LaF class name, as you do, and you don't print the exception, you might actually not come to know what's going wrong.
Sequence of widget construction and UIManager.setLookAndFeel()
The sequence of UIManager.setLookAndFeel() and the effective new JFrame() via super(...) does not guarantee you that the whole UI will be in Nimbus, parts of it might still be in Metal. I recommend to set the LaF before even constructing the first widget, to be on the safe side. As far as I remember, it's not guaranteed that changing the LaF after component construction has an effect, unless you tell the UIManager to update the LaF. See also this quote from the documentation of UIManager:
Once the look and feel has been changed it is imperative to invoke updateUI on all JComponents. The method SwingUtilities.updateComponentTreeUI(java.awt.Component) makes it easy to apply updateUI to a containment hierarchy. Refer to it for details. The exact behavior of not invoking updateUI after changing the look and feel is unspecified. It is very possible to receive unexpected exceptions, painting problems, or worse.
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
setSize() vs. pack() with a little help of Insets and Border
Instead of setting the size manually, you might want to play with Insets or Border and JFrame.pack() in order to get a decent layout of your window. Setting the size manually assumes that you know a lot about the screen resolution and the font size of the user.
The pack() method performs automatic size calculation based on the contents. Insets and Border allow you to create some space and borders, even with some designs or labels, around components so they wouldn't be cramped tightly in a window but be nicely spaced.
First you have to assign an actionListener to the ReFresh Jbutton.
You can either implement the interface ActionListener to the class, and override the actionPerformed() method like this
public class View extends JFrame implements ActionListener{
private JButton ReFresh;
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
ReFresh = new JButton("ReFresh");
ReFresh.addActionListener(this);
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() { //right way for nimbus: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/nimbus.html
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.equals(ReFresh))
{
super.repaint();
}
}}
public static void main(String[] args) {
View pdf = new View();
}
Or you can do inline assignment to addActionListener, like this
ReFresh.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
super.repaint();
}
});
You can try these methods to refresh/reload the JFrame,
invalidate();
validate();
repaint();
you can also use dispose(); and then new View(); to create the new JFrame, but in this sequence it will close the window and create new one.
or you can even try setVisible(false); then setVisible(true);
I recommend the first 3.

How do I remove the blue border highlight that appears when selecting a tab in a JTabbedPane?

This is sort of a continuation of my previous question, but it addresses a specific concern that could be useful to someone else so I thought I would post it as a individual question.
I have successfully created a JTabbedPane but there is an blue border highlight that shows which tab has been selected that I would like to remove:
To clarify what I mean here is a picture of a JTabbedPane without the blue border highlight from Eclipse:
The things I have tried have been commented out:
public class SeaGlassExercise {
public static void initWindow() {
JFrame frame = new JFrame("Application Name");
CustomTabbedPane content = new CustomTabbedPane();
frame.setContentPane(content);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(true);
// try {
// UIManager.setLookAndFeel(
// UIManager.getSystemLookAndFeelClassName());
// } catch (Exception e) {
// e.printStackTrace();
// }
// SwingUtilities.updateComponentTreeUI(frame);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initWindow();
}
});
}
}
class CustomTabbedPane extends JPanel {
public CustomTabbedPane() {
super(new GridLayout(1, 1));
// UIManager.put("TabbedPane.contentAreaColor", Color.GREEN);
// UIManager.put("TabbedPane.light", ColorUIResource.GREEN);
// UIManager.put("TabbedPane.highlight", ColorUIResource.GREEN);
// UIManager.put("TabbedPane.shadow", ColorUIResource.GREEN);
// UIManager.put("TabbedPane.darkShadow", ColorUIResource.GREEN);
// UIManager.put("TabbedPane.selected", ColorUIResource.GREEN);
// UIManager.put("TabbedPane.borderHightlightColor", ColorUIResource.GREEN);
// UIManager.put("TabbedPane.borderHightlightColor", ColorUIResource.GREEN);
// UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0));
JTabbedPane tabbedPane = new JTabbedPane();
JComponent panel1 = makeTextPanel("Panel #1");
tabbedPane.addTab("AAA", panel1);
JComponent panel2 = makeTextPanel("Panel #2");
tabbedPane.addTab("BBB", panel2);
JComponent panel3 = makeTextPanel("Panel #3");
tabbedPane.addTab("CCC", panel3);
JComponent panel4 = makeTextPanel("Panel #4");
tabbedPane.addTab("DDD", panel4);
add(tabbedPane);
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
}
protected JComponent makeTextPanel(String text) {
JPanel panel = new JPanel();
JLabel filler = new JLabel(text);
filler.setHorizontalAlignment(JLabel.CENTER);
panel.setLayout(new GridLayout(1, 1));
panel.add(filler);
return panel;
}
}
Additional Information
I am currently running my program with OS X Mountain Lion along with java version "1.7.0_25", Java(TM) SE Runtime Environment (build 1.7.0_25-b15). I am using the default look and feel (i.e. I have not specified anything with .setUI() in my code).
Here are some questions I have looked at:
Controlling Color in Java Tabbed Pane
JTabbedPane - set default border around tabs..?
remove blue color from JTabbedPane
Note the current approach may not work with other platforms / look and feels. If your current project is intended to work only on your Mac and you don't plan change this in the future, well in that case it might work. But normally Java applications are intended to work across different platforms and look and feels.
Having said this you may want to take a look to this interesting article about most popular look and feels defaults: All UI defaults names for common Java look and feels on Windows, Mac OS X, and Linux. When you look at the tables then you'll see not all L&Fs support the same properties and may ignore them when create an UI object (f.i. TabbedPaneUI).
If you like Mac L&F (I do) then I'd suggest you try customizing Seaglass Look and Feel which is pretty similar than Mac's. This way you will get this benefits:
Standard cross-platform L&F similar to Mac's L&F provided with your app.
Customize the L&F and this change will be also cross-platform.
Unify user experience (non trivial matter). Probably you and me will be able to work with the same app on Mac OS, Windows or Linux with different L&F. But many users can't do it: they get lost when the GUI looks different.
To customize Seaglass you can list the default properties as follow:
for(Object key : UIManager.getLookAndFeel().getDefaults().keySet()) {
System.out.println(key + " = " + UIManager.get(key));
}
These are quite much and I really don't have time enough to give you a working example so I hope the idea is good enough to help you.
Note
If you don't want frames and dialogs have the default decoration provided with Seaglass (it's pretty ugly to me) then you need to do as follw:
UIManager.setLookAndFeel(new SeaGlassLookAndFeel());
JFrame.setDefaultLookAndFeelDecorated(false);
JDialog.setDefaultLookAndFeelDecorated(false);
This way frames and dialogs will have their Window decorations provided by the current window manager (up to the OS).
I know the correct visual solution to remove tabs' border:
tabbedPane.setFocusable(false);
But you lost posibility to use keys for tabbed pane.
I believe setting the border will remove these... it does on a JTextField.
For example:
JTextField field = new JTextField();
field.setBorder(new EmptyBorder(3, 3, 3, 3));
This removes the blue focus border.

JTabbedPane: avoid automatic re-ordering tabs if stacked / Nimbus

a JTabbedPane is just what I need for my purpose.
I have very limited horizontal space, so my Tabs get stacked, which is perfectly ok.
But the default behaviour is that if user clicks on a Tab, the *Tabs get re-sorted so that the active Tab becomes the lower-mos*t. What looks very intuitive and logical in theory, is a nightmare in practical use, because the users loose track of "which was which". Its just simply plain confusing, I am told again and again.
I guess it should be possible to override some method of the UI to avoid this behaviour (and I dont care whether this would be physically possible with paper cards :-) .
Has anyone any idea where I need to do that? I am using Nimbus LAF, which does not seem to make it easier.
(I thought about using radiobuttons/cardLayout, but I need to put a custom panel in the tab title, and radiobuttons can only have a string or icon. Same for JToggleButton...)
Any hints are greatly welcome!
Thanks & Kind regards,
Philipp
sscce for potential answerer(s) for Nimbus L&f (by using another L&f isn't possible to reproduce this funny issue), in case that Containers#Size packed Tabs to the two or more Lines,
as I know there is only one possible solutions (without override NimbusTabbedPaneUI) by aephyr
from sscce
import java.awt.BorderLayout;
import javax.swing.*;
public class TabbedPane {
private static final long serialVersionUID = 1L;
public TabbedPane() {
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
JTabbedPane tb = new JTabbedPane();
//tb.setUI(new CustomTabbedPaneUI());
tb.add("Tab1", new JTextArea(10, 20));
tb.add("Tab2", new JTextArea(10, 20));
tb.add("Tab3", new JTextArea(10, 20));
tb.add("Tab4", new JTextArea(10, 20));
tb.add("Tab5", new JTextArea(10, 20));
jp.add(tb, BorderLayout.CENTER);
//add(jp, BorderLayout.CENTER);
//tb.setEnabledAt(1, false);
//tb.setEnabledAt(3, false);
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(jp, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception system) {
system.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TabbedPane tP = new TabbedPane();
}
});
}
}
Okay, I found the Problem. In
package javax.swing.plaf.basic.BasicTabbedPaneUI;
it says something like this
// Rotate run array so that selected run is first
if (shouldRotateTabRuns(tabPlacement)) {
rotateTabRuns(tabPlacement, selectedRun);
}
Its a pity that there seems to be no easy set-a-flag-and-there-you-go-way is for changing that.
Although you should be fine if you omitted the call to rotateTabRuns(tabPlacement, selectedRun); or change shouldRotateTabRuns(tabPlacement) for that matter... however, to do so you would have to override a whole bunch of classes... depending on which plaf you use.
It inherits like this
Basic > Synth > Nimbus
And on each L&F-level there are several classes to customize... I didn't count.
Hope it helps! :D
Edit
Oh yeah... #mkorbel already provided sort of the solution with this aephyr why not use that?
It's a bit of a hack but you can override the Nimbus defaults to have the plain old Java look-and-feel for the tabbed pane, whilst keeping everything else the same. The plain Java look-and-feel for a tabbed pane doesn't do the annoying reordering. Just store the defaults before you set the look-and-feel and then set them back.
// get the defaults to keep
HashMap<Object, Object> defaultsToKeep = new HashMap<>();
for (Map.Entry<Object, Object> entry : UIManager.getDefaults().entrySet()) {
boolean isStringKey = entry.getKey().getClass() == String.class ;
String key = isStringKey ? ((String) entry.getKey()):"";
if (key.startsWith("TabbedPane")) {
defaultsToKeep.put(entry.getKey(), entry.getValue());
}
}
// set nimbus look and feel
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
// set back your originals
for (Map.Entry<Object, Object> entry : defaultsToKeep.entrySet()) {
UIManager.getDefaults().put(entry.getKey(), entry.getValue());
}
JFrame.setDefaultLookAndFeelDecorated(true);

How to force an HTML JLabel in a JTree to resize when the font changes

I'm updating a Java Swing application to support the user switching the app's font from normal size to a larger size (so the user can switch between the two sizes at runtime). One problem I'm having is with a JTree that uses HTML for the tree nodes to underline the text in some nodes (the HTML is just embedded in the JLabel of each tree node). One extra thing to know about the nodes is that they're a custom component, adding a JCheckBox in front of each JLabel.
The problem is that once the JTree is visible, increasing the font size causes the nodes (containing underlined text) to not resize. The HTML for those nodes seems to prevent the node from becoming wider, so when the font changes, the text becomes truncated.
I think my options are to either: 1) use another approach to make the text underlined, since removing the HTML from the JLabel causes it to resize properly when the font size changes, or 2) keep the HTML formatting and somehow force the JTree/JLabels to resize when the font size is updated (possibly by firing a property change event?).
The code already calls SwingUtilities.updateComponentTreeUI() on the parent JFrame when the font size gets updated.
EDIT: The method used to change the font in the application is explained here.
Any help would be greatly appreciated. Thanks in advance!
-Mike
I cannot recreate the problem you describe. Here is a test program that works for me on JavaSE 6:
public class JTreeFontResize {
private static JTree tree;
private static JFrame frame;
public static void main(String[] args) throws InterruptedException,
InvocationTargetException {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
tree = new JTree(new Object[] { "One (plain)",
"<html><u>Two (HTML)", "<html>Three (HTML)" });
frame = new JFrame("Tree Font Resize");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 100, 300, 300);
frame.add(tree);
frame.setVisible(true);
}
});
Thread.sleep(2000);
changeFontSize(20);
Thread.sleep(2000);
changeFontSize(30);
Thread.sleep(2000);
changeFontSize(12);
}
private static void changeFontSize(final int size) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Font font = new Font("Vernanda", Font.PLAIN, size);
FontUIResource fontResource = new FontUIResource(font);
Enumeration<Object> keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = UIManager.get(key);
if (value instanceof FontUIResource) {
UIManager.put(key, fontResource);
}
}
SwingUtilities.updateComponentTreeUI(frame);
}
});
}
}
If the above works for you then maybe you should post a cut down version of your problematic code.

Categories