The JCombobox's "content" window has this blue highlight that i don't know how to get rid of, please help.
Here is an example of the problem:
package example;
import java.awt.CardLayout;
import java.awt.Color;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(1);
frame.setSize(500, 500);
frame.setLayout(new CardLayout());
frame.setVisible(true);
JPanel panel=new JPanel();
panel.setLayout(null);
frame.add(panel);
String[] model = {"pres.", "PPS.", "P. inp.", "P. mais q."};
JComboBox combox;
combox = new JComboBox(model);
combox.setBounds(100, 100, 145, 30);
combox.setBackground(new Color(215, 211, 165));
combox.setFocusable(false);
panel.add(combox);
panel.updateUI();
}
}
The combo box is a complex components that uses multiple components internally. The UI determines how the components interact with one another.
For example change your code to the following:
JComboBox combox;
combox = new JComboBox(model);
combox.setBorder( new LineBorder(Color.YELLOW) );
BasicComboBoxRenderer renderer = new BasicComboBoxRenderer();
renderer.setBorder( new LineBorder(Color.RED) );
combox.setRenderer(renderer);
And you will notice that the blue highlight is not a border of the combo box or its render, implying there is another internal container we don't have access to.
If you really want to solve the problem then you will need to customize the MetalComboBoxUI class, which is never an easy task because many of the painting methods will be private. But take a look at the code of the class to see if it can be done.
Other issues with your code:
Don't use updateUI(). The method is invoked internally in Swing when the LAF is changed. You are not changing the LAF
Components should be added to the frame BEFORE the frame is visible. This will eliminate the need for the updateUI().
Related
The below code creates a frame with a JTabbedPane in the frame's contentPane and a "Help" button added directly to the frame's layered pane - at a higher index than the default, so it should always be painted in front of the tabbed pane. But as you can see if you run it, as soon as you click on one of the tabs (or, on Mac, as soon as you hover over a tab), the "Help" button gets painted over - i.e. disappears. You have to resize the frame to make the "Help" button re-appear.
Is this a Java bug or am I doing something wrong? If the latter, what needs to be done to fix the problem? I've consulted both https://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html and https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html .
Please pardon the poor positioning of the "Help" button. I was just trying to write a quick test to include here. The idea is the to overlay a "Help" icon button in the unused space of the JTabbedPane.
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public class TabTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
JTabbedPane tp = new JTabbedPane();
tp.addTab("hello", new JPanel());
tp.addTab("there", new JPanel());
frame.getContentPane().add(tp, BorderLayout.CENTER);
JLayeredPane layeredPane = frame.getRootPane().getLayeredPane();
JButton helpButton = new JButton("Help");
helpButton.setBounds(800, 5, 50, 20);
layeredPane.add(helpButton, 400);
frame.setSize(new Dimension(900, 800));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
This is a common misunderstanding with JLayeredPane.
If you have a look at the JavaDocs for Container, you will note that there are (at least) two add methods
Container#add(Component, int)
Container#add(Component, Object)
The question you need to answer is, which one are you actually calling?
Both the JavaDocs for JLayeredPane and How to use JLayeredPane demonstrate that you should be calling the second one.
While the first can affect the z-ordering of the components, it's no guarantee that the component positions won't be changed.
Instead of:
layeredPane.add(helpButton, 400);
you should be using:
layeredPane.add(helpButton, new Integer(400));
which will pass the value as a constraint to the container, instead of the desired position within the container hierarchy - yeah, suitable I know
An alternative solution might be to use the glassPane instead, for example...
JFrame frame = new JFrame();
JTabbedPane tp = new JTabbedPane();
tp.addTab("hello", new JPanel());
tp.addTab("there", new JPanel());
frame.getContentPane().add(tp, BorderLayout.CENTER);
// Null layout used here for demonstration purposes only
JPanel glassPane = new JPanel(null);
glassPane.setOpaque(false);
frame.getRootPane().setGlassPane(glassPane);
// This is important, as setGlassPane makes it invisible
glassPane.setVisible(true);
JButton helpButton = new JButton("Help");
helpButton.setBounds(800, 5, 50, 20);
glassPane.add(helpButton);
frame.setSize(new Dimension(900, 800));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
I have an java assignment in which I need to have the background color of a GUI change depending on user selected radio buttons listing different colors.
My program has a JFrame to hold everything, then 3 JPanels (1 Instruction area, 1 Radio Button grid, 1 result Textfield) within that frame.
My action listener is currently setting the background color with this statement: getContentPane().setBackground(Color.decode(colorMap.get(btn.getName())));
The background for the JFrame and two of the three panels successfully changes to the correct color, but the panel holding the JRadioButtons will not change at all!
I have tried changing the opaque setting, I have tried setting the panel's background color to (0,0,0,0) but so far none of that is working for me. Does anyone have a suggestion of what I might try or read up on next?
I don't have enough reputation to post a picture but if seeing what I'm talking about helps, let me know and I can email you a screenshot.
Thanks!
You must additionally set all JRadioButtons.setOpaque(false).
Example with one JRadioButton opaque and one non-opaque:
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class XFrame
extends JFrame
{
public XFrame(String title)
{
super(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JRadioButton b1 = new JRadioButton("Non opaque button");
// button must not be opaque
b1.setOpaque(false);
// this button is opaque and does not use the background color of the frame
JRadioButton b2 = new JRadioButton("Opaque button");
JPanel p1 = new JPanel();
// panel must be non opaque also
p1.setOpaque(false);
p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
p1.add(b1);
p1.add(b2);
add(p1, BorderLayout.CENTER);
getContentPane().setBackground(Color.red);
setSize(200, 200);
}
public static void main(String[] args)
{
XFrame frame = new XFrame("Test");
frame.setVisible(true);
}
}
in this code when the new button is clicked, the Jinternalframe goes behind the button, even if i add anything else like, jlabel, jtextfield, etc, the internalframe opens behind everything. i tried the tofront() and movetofront() functions, but it doesnt seem to work. plz help, thanks.
code:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Messages2 extends JFrame {
JFrame frame;
JButton button1;
public static void main(String[] args) {
Messages2 window = new Messages2();
window.frame.setVisible(true);
}
public Messages2() {
frame = new JFrame();
frame.getContentPane().setBackground(Color.WHITE);
frame.setBounds(100, 100, 220, 220);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//frame.getContentPane().setLayout(new FlowLayout());
JButton btnNew = new JButton("New Message");
btnNew.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JDesktopPane desktopPane = new JDesktopPane();
JInternalFrame intFrame = new JInternalFrame(
"JInternalFrame demo");
intFrame.setMaximizable(true);
intFrame.setIconifiable(true);
intFrame.setResizable(true);
intFrame.setClosable(true);
intFrame.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
intFrame.setSize(320, 240);
// intFrame.pack();
intFrame.setVisible(true);
desktopPane.add(intFrame);
frame.add(desktopPane, BorderLayout.CENTER);
}
});
btnNew.setBounds(1, 35, 145, 31);
frame.getContentPane().add(btnNew);
}
}
when the new button is clicked, the Jinternalframe goes behind the button, even if i add anything else like, jlabel, jtextfield, etc,
Based on the code you posted in you last question (before you deleted it), you are attempting to add all your components directly to the frame. Swing paints components in the reverse order that a component is added. So since the internal frame is added last it is painted first and then all the other components are painted over top of it.
This is not the way you should be working with a JInternalFrame. You need to separate the JDesktopPane/JInternalFrames from your other components and work with each separately.
Read the section from the Swing tutorial on How to Use Internal Frames for basic information and examples.
the internal frame is added to a JDesktopPane which is added to the frame.
Don't use a null layout for your other components. Swing was designed to be used with layout managers. These components should be added to a panel and then the panel added to the frame.
The panel and the desktop pane must be added to different areas of the frame. For example:
frame.add(panel, BorderLayout.NORTH);
frame.add(desktopPane, BorderLayout.CENTER);
You're not using JInternalFrame correctly. It should only be placed within a JDesktopPane, something you're not doing and that I suggest that you start doing. Please check the appropriate tutorial on this.
Your button and your JInternalFrame now fill the field since you're using the JFrame's default BorderLayout. Suggestion:
First and foremost, explain fully just what exact effect/user experience you're trying to achieve. Are you sure that a JInternalFrame is your best choice here?
Learn about and use the layout managers to their best advantage.
If you're going to use a JInternalFrame, then while it's OK to add the JInternalFrame in your ActionListener, you're usually going to want to add the JDesktopPane to the GUI on GUI creation, not in the ActionListener.
I have a JTextField being added to an OverlayLayout, but the JTextField automatically scales to be the dimensions of the entire panel, which I don't want. I also don't want to mess with the dimensions of the JTextField because the default height is just right for the font, and the width is supposed to be defined by the number of columns in the constructor. What would be the right way to fix this?
Here's the relevant code that I have now:
frame = new JFrame("frame");
frame.setResizable(false);
panel = new GamePanel();
panel.setPreferredSize(new Dimension(500,300));
panel.setLayout(new OverlayLayout(panel));
JTextField t = new JTextField(50);
panel.add(t);
frame.add(panel);
frame.pack();
frame.setVisible(true);
GamePanel is just a subclass of JPanel; it doesn't do anything that would affect the JTextField.
EDIT: ok, I've heard now that using the default Swing layout managers isn't the best idea. kleopatra linked a page that refers to three third-party layouts that should accomplish pretty much everything you need to do, but I can't find anything that would let me overlay a text field (or other component) onto another custom-rendered panel. What would be the right approach?
Does this work as you want it?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.LayoutManager;
import javax.swing.JTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.OverlayLayout;
public class OverlaySampleAlignment0 {
public static void main(String args[]) {
JFrame frame = new JFrame("Overlay Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(500,300));
LayoutManager overlay = new OverlayLayout(panel);
panel.setLayout(overlay);
JTextField field = new JTextField("", 12);
field.setMaximumSize(field.getPreferredSize());
//button.setMaximumSize(new Dimension(25, 25));
field.setBackground(Color.white);
field.setAlignmentX(0.0f);
field.setAlignmentY(0.0f);
panel.add(field);
frame.add(panel);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
}
The height is exactly the height needed for the font, and the width is (in my example) 12 "columns" (JTextField does not use a monospaced font by default in my Java setup). Additionally I aligned it in the upper left corner.
This might also help trouble-shooting layout issues:
Link
Most of the code is copied from here: Link. I just added the setMaximumSize(...) and used a JTextField instead of buttons etc.
So I have a gui where the layout is set to Null, and I put JLabels ontop of JButtons since the JButtons have icons and adding text to the button makes the button look distorted, so instead I am using JLabels ontop of the JButtons. Every time the mouse goes over the JButton when I test it, the JLabel disappears. How can I fix that so JLabels always appear above JButtons.
Edit: it distorts the button so the icon is taking up most the space and the button label is cut off by the opposite edge of the button.
If you're using a JFrame, as I assume you must be, you could add the labels to a JLayered pane that sits on top of the content pane.
There is almost no cases when you will need to use null layout. You just need to do a little practice with the LayoutManagers
You can do the thing you wish to do with a JLayeredPane. Like this:
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(jLabelOnJButton());
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static JComponent jLabelOnJButton(){
JLayeredPane layers = new JLayeredPane();
JLabel label = new JLabel("label");
JButton button = new JButton("button");
label.setBounds(40, 20, 100, 50);
button.setBounds(20, 20, 150, 75);
layers.add(label, new Integer(2));
layers.add(button, new Integer(1));
return layers;
}
}
This is not a good solution I think. Only do it if you have no better solution.