I'm writing a program that trades out the main component of the GUI when a button is pressed. To do this, I have multiple classes extending a component (JScrollPane) that can then be placed into my main class, which extends JFrame.
JScrollPane menu;
public MenuSystem()
{
menu = new OpeningMenu(this);
setSize(500,500);
setLocationRelativeTo(null);
setTitle("Menu system");
setDefaultCloseOperation(EXIT_ON_CLOSE);
loadInfo();
pane = getContentPane();
pane.setLayout(null);
pane.add(menu);
setVisible(true);
}
public void changeMenuTo(JScrollPane x)
{
pane.remove(menu);
menu = x;
pane.add(menu);
pane.repaint();
}
These bits of code control which JScrollPane is displayed on the GUI. I face two problems that I believe are related.
When I start the program, some of the components in the initial JScrollPane do not appear. I have several buttons and a JLabel in this pane, but only the first button appears. The rest of the buttons will appear when my mouse passes over them, but until then, they are invisible. This seems strange, because it suggests that my constructor is somehow at fault. when bringing up the same pane with the changeMenuTo() method, it appears perfectly.
Whenever I manually resize the screen, all components in the current pane disappear. It happens almost exactly like when I first start the program, buttons are invisible until my mouse passes over them. In this case the first button is also invisible.
Changing the layout has fixed the issue. Thanks for the suggestions.
Related
I've started adding a few buttons to my new Java Swing project (first time using Swing) and I tried adding a mouse listener event to them with the intention of having the background of the (transparent) button to change to a darker color when the mouse is hovering over it.
I did this using JPanels behind the the buttons, and I tried changing their backgrounds to a 50% opaque color.
Code:
for(int i=0;i<5;i++){
JPanel p = new JPanel();
p.setOpaque(false);
b[i].setContentAreaFilled(false); //b is an array consisting of 5 buttons
b[i].setForeground(Color.RED); //
b[i].addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
p.setOpaque(true);
p.setBackground(new Color(0,0,0,50));
}
public void mouseExited(MouseEvent e){
p.setOpaque(false);
p.setBackground(new Color(0,0,0,0));
}
p.add(b[i]);
}
I have multiple unexpected things happen with this code:
Every time I click the button (I have no ActionListener on them) the button (and only the button, not the panel behind it) gets increasingly darker until it reaches black.
If I hover over a (white) button in another part of the program first, then over any of these buttons the panels behind them become white instead of a darker version of the original color.
If I hover over any of these buttons, and then over another one of them afterwards, the second button seems to display the text of BOTH of the buttons.
Screenshots:
1: https://cdn.discordapp.com/attachments/871490774301294642/957684879712219168/unknown.png
2: https://cdn.discordapp.com/attachments/871490774301294642/957685306562338826/unknown.png
3: https://cdn.discordapp.com/attachments/871490774301294642/957685596900438086/unknown.png
Maybe I'm doing something blatantly wrong but I'm quite new to Swing so sorry if that is the case. Any help appreciated.
private void jBtnAboutActionPerformed(java.awt.event.ActionEvent evt) {
jPanel_About.setSize(300, 300);
jPanel_About.setVisible(true);
}
How can I make User unable to select the main jFrame where jBtn_About is located while the About Panel pop-up?
Also, the code does show a new panel but it's created at top left corner of display. How can i allign it to be created in middle of the main jFrame?
Thank you very much!
You can use JDialog (as modal window) instead of jPanel_About.
For JDialog you can use setLocation to place it in desired position.
I tried to add a series of buttons to the container of a frame. But I found that the last button added to the container always occupy the whole screen instead of at the correct position. How can I fix this problem?
Here is the code used to add these buttons:
for(int i = 0; i < n; i++)
{
button[i] = new JButton();
container.add(button[i]);
button[i].setText(NAME[i]);
button[i].setBounds(WIDTH-OFFSET_EDGE-bd.w, OFFSET+i*(bd.h+bd.gap), bd.w, bd.h);
button[i].addActionListener(handler);
button[i].setVisible(true);
}
The container is get as following:
Container container = this.getContentPane();
The main class is the subclass of JFrame:
public class SimpleTextDemo extends JFrame
Now my solution is to use an extra button which is not visible so that the useful buttons can be at their correct location. But it seems that this method is QUITE stupid...
The default layout for JFrame is BorderLayout. If you add button to JFrame than it will occupy whole container. Change your layout using setLayout method.
In java the default layout is set to the container is BorderLAyout() To add them properly you'll have to explicitly mention the position of the button to be added. All of these buttons you are adding will be added to the center. Finally all of'em are getting overlapped. To avoid this you can give them positions like CENTER , EAST, WEST, NORTH, SOUTH.
The reason for displaying only last button is all of'em are getting overlapped.
I am trying to create a JScrollPane that contains a JPanel that will be increasing and decreasing in height. When it becomes larger than the size of the JScrollPane, it should create a vertical scroll bar which will allow me to scroll through the entire JPanel. However, I am having difficulty achieving this. Yes, I know I am not using LayoutManagers. No, I will not be using them, and I need a solution that does not involve their usage.
Here are the two button's AbstractActions that add and subtract from the JPanel:
class AddACT extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
info.setSize(420,info.getHeight() + 40);
info.add(new SubPanel); // Adds another JPanel into the main JPanel (for content input)
gui.repaint();
infoS.validate();
}
}
class RemoveACT extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
info.remove(subPanel()); // This would remove the last JPanel added to the main JPanel
info.setSize(420,info.getHeight() - 40);
gui.repaint();
infoS.validate();
}
And here is the code for the main JPanel and the JScrollPane:
final JPanel info = new JPanel();
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
info.setLayout(null);
info.setSize(420,600);
infoS.setLocation(10,80);
infoS.setSize(420,490);
gui.add(infoS); // gui is the frame's content pane (the overall JPanel)
This is the second project I've been trying to learn GUI by doing. I am a complete novice in Swing and am only intermediate in Java. Sorry if I am making a blindingly obvious mistake.
1) Use LayoutManagers (+1 to #kleopatra and #GagandeepBali comments)
The absence of LayoutManagers only guarantees your GUI's will look very trashy (especially when run on other OSes/builds) and being a Novice you should rather learn the correct way than learn the wrong way and get into bad habits like calling setSize() etc.
Have a read on these links to get you started:
A Visual Guide to Layout Managers
Concurrency in Swing
2) See this example for how to use a JScrollPane, it simply adds a JPanel with buttons to a JScrollPane which in-turn is added to the JFrame.
3) Also see this example for how to make the JScrollPane vertically scroll-able only.
4) For more on JScrollPanes have a look here: How to Use Scroll Panes.
5) As for how it interacts with LayoutManager, if you do not explicitly set its size via setPreferredSize(Dimension d) the scroll pane computes it based on the preferred size of its nine components (the viewport, and, if present, the two scroll bars, the row and column headers, and the four corners)
6) On your usage of validate():
validate() is used when new JComponents are added to a visible component
revalidate() is used when JComponent is removed/added from a visible component
revalidate() covers validate() too
Thus always use this:
//add or remove component(s)
revalidate();
repaint();
References:
http://www.daniweb.com/software-development/java/threads/405568/validate-vs-revalidate
LayoutManager is not required to solve the problem. The problem in Thrfoot's example is in these lines:
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
info.setLayout(null);
info.setSize(420,600);
The program appears to recognize there is a need for scroll bars (it would show the scroll bar if your setting was VERTICAL_SCROLLBAR_AS_NEEDED), but the actual scrolling does not work (the scroll bar slider is not there).
To fix this, first set the preferred size of info, then construct the infoS.
Example:
info.setPreferredSize(420,600);
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
The idea is to set the preferred size of the info panel before it is used for the scroll pane. This is the same reason to set the size and location of infoS before adding to the gui:
infoS.setLocation(10,80);
infoS.setSize(420,490);
gui.add(infoS); // gui is the frame's content pane (the overall JPanel)
So I have a JFrame in which inside of it I have a JScrollPane and inside the JScrollPane I have a JPanel. I have a button click mouse listener that modifies the JPanel inside the JScrollPane. The code in the mouse listener is:
#Override
public void mouseClicked(MouseEvent arg0) {
searchResult.updateInfo();
}
The method updateInfo is adding a bunch of JPanel into the searchResult JPanel. After I click the button associated with this listener, nothing happens, but when I resize the JFrame.. it updates the view.. why is this?
I tried repaint the JFrame, but it did not solve my problem
After adding/removing components from a visible GUI you need to tell the panel to layout the components so the preferred size can be recalculated. You need to add:
searchResult.revalidate();
searchResult.repaint(); // sometimes needed
Then if the preferred size is greater than the size of the scrollpane scrollbars will appear.
make
searchResult.removeAll();
searchResult.updateInfo();
searchResult.validate();
if it doesn't work make like this
searchResult.removeAll();
searchResult.updateInfo();
searchResult.validate();
searchResult.repaint();