I have a couple of JRadioButton: rb1, rb2; which is contained in transparent JPanel p1, and p1 is contained in a colorful panel, named mainPanel.
I want to make these JRadioButton transparent too and here is what I do:
in mainPanel: mainPanel.setBackground(Color.RED);
in p1: p1.setBackground(new Color(0,0,0,0));
and in rb1 and rb2:
rb1.setOpaque(false);
rb1.setContentAreaFilled(false);
rb1.setBorderPainted(false);
rb2.setOpaque(false);
rb2.setContentAreaFilled(false);
rb2.setBorderPainted(false);
it's ok if rb1 and rb2 is contained in mainPanel or if p1 isn't a transparent JPanel, but in my case, the outcome is not what i expected:
How can I resolve this problem? Thanks in advance!
The weird painting artifacts you're seeing are caused by this:
p1.setBackground(new Color(0,0,0,0));
With that the parent container will not be notified to clear it's background and repaint. So if you want the panel to be completely transparent, just use setOpaque(false) instead. You also just need to call this method on the radio buttons and nothing else.
setOpaque will notify the parent to repaint, but if you want a semi-transparent panel, you have to override paintComponent and call super.paintComponent(Graphics) manually.
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class Example {
public void createAndShowGUI() {
JRadioButton encryptButton = new JRadioButton("Encrypt");
encryptButton.setOpaque(false);
JRadioButton decryptButton = new JRadioButton("Decrypt");
decryptButton.setOpaque(false);
ButtonGroup group = new ButtonGroup();
group.add(encryptButton);
group.add(decryptButton);
JPanel subPanel = new JPanel();
subPanel.setOpaque(false);
subPanel.add(encryptButton);
subPanel.add(decryptButton);
JPanel mainPanel = new JPanel();
mainPanel.setBackground(Color.CYAN);
mainPanel.add(subPanel);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example().createAndShowGUI();
}
});
}
}
Related
This is the add(main) version
This is the add(scroll) version
Im trying to get a window full of lables and make it scrollable, this is my code for that purpose:
public class JobHistoryListScreen extends JFrame implements View
{
#Override
public void showScreen()
{
setSize(800, 800);
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel main = new JPanel();
main.setSize(500,500);
JScrollPane scroll = new JScrollPane(main,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setSize(500,500);
//Font
//Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++)
{
JLabel empty = new JLabel("No jobs to display!");
empty.setBounds(0,i+250,400,100);
empty.setFont(david50);
main.add(empty);
}
add(main);
setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
v.showScreen();
}
}
For some reason the window gets filled with the labels but is not scrollable at all.
Learn about layout managers. Refer to Laying Out Components Within a Container. Default for JPanel is FlowLayout and because the JPanel is inside a JScrollPanel, the labels will not wrap. And since you set the horizontal scroll bar policy to NEVER, there is no horizontal scroll bar and hence you cannot scroll horizontally. Try using BoxLayout to display all the labels one under the other. Alternatively you could use a GridLayout with 0 (zero) rows and 1 (one) column. Refer to the tutorial for more details.
EDIT
Here is my modified version of your code. Explanatory notes appear after the code.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class JobHistoryListScreen implements Runnable {
private JFrame frame;
#Override // java.lang.Runnable
public void run() {
showScreen();
}
public void showScreen() {
frame = new JFrame("Jobs");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel main = new JPanel(new GridLayout(0, 1));
JScrollPane scroll = new JScrollPane(main,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setPreferredSize(new Dimension(500, 500));
Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++) {
JLabel empty = new JLabel("No jobs to display!");
empty.setFont(david50);
main.add(empty);
}
frame.add(scroll);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
// Launch Event Dispatch Thread (EDT)
EventQueue.invokeLater(v);
}
}
I don't know what interface View is so I removed that part.
No need to extend class JFrame.
No need to explicitly call setSize() on JFrame. Better to call pack().
Default content pane for JFrame is JPanel and default layout manager for that JPanel is BorderLayout so no need to explicitly set.
No need to call setSize() on JPanel.
Call setPreferredSize() rather than setSize() on JScrollPane.
Add the JScrollPane to the JFrame and not the JPanel.
No need to call setBounds() because GridLayout handles this.
Explicitly launch EDT (Event Dispatch Thread) by calling invokeLater().
Here is a screen capture of the running app. Note the vertical scroll bar.
I have a JFrame, and within it, a JLabel that is filled by an image of a Map. I want to have clickable square “Tiles” in a grid over the image of the map. To do this, I made a large grid of JButtons that I have added to the JLabel containing the Map. However, the Map cannot be seen, so I have made the JButtons completely transparent. However, when they are Transparent, I can’t see where one JButton ends, and where another one starts. I want to create a JButton that is totally transparent on the inside, but still has a visible border around it. I have tried setOpaque(false) and then setBorderPainted(true) but that makes them opaque again. I have tried everything I could find, but nothing happens. Any suggestions?
Once again, all I want is a Transparent JButton with Visible Borders
You should be able to replace border with you own...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.RED);
setLayout(new GridBagLayout());
JButton btn = new JButton("Hello");
btn.setOpaque(false);
btn.setContentAreaFilled(false);
btn.setBorderPainted(true);
btn.setBorder(new LineBorder(Color.BLUE));
add(btn);
}
}
}
You might need to use a CompoundBorder with a EmptyBorder on the inside to provide some padding (I tried using setMargins but it didn't seem to work)
I'm trying to align a JLabel to the right in a JPanel. I'm adding a JTabbedPane, a JPanel which contains my JLabel and JTextArea to a main JPanel.
I have searched SO and tried some methods like setAlignmentX, setHorizontalAlignment(SwingConstants.LEFT) and nested containers to no avail.
Here's my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class LabelProblem
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Label Problem");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel Main = new JPanel();
Main.setLayout(new BoxLayout(Main, BoxLayout.Y_AXIS));
JPanel ComponentPanel = new JPanel();
JLabel label = new JLabel("Sample Text");
label.setHorizontalAlignment(SwingConstants.LEFT);
label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
label.setAlignmentX(Component.RIGHT_ALIGNMENT);
ComponentPanel.add(label);
JTabbedPane Tab = new JTabbedPane();
Tab.add("Document 1", new JPanel());
Main.add(Tab);
Main.add(ComponentPanel);
JTextArea Area = new JTextArea(10,10);
JScrollPane Scroll = new JScrollPane(Area);
frame.add(Main);
frame.add(Scroll, BorderLayout.SOUTH);
frame.setSize(450,450);
frame.setVisible(true);
}
}
How can I align my JLabel to the right?
Thanks!
So, the place of that label is determined by the layout of ComponentPanel. Since you didn't specify any layout it is using the default FlowLayout with a CENTER alignment. Assuming that you are ok with a FlowLayout it is a mere question of setting the alignment of the LEFT since this is possible with this layout.
Here's the code with the fix, however I suspect that as you put more elements to the ComponentPanel you will want to use another layout since FlowLayout is more adequate for menus and the like and not for displaying the main content.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
class LabelProblem
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
initGUI();
}
});
}
public static void initGUI()
{
JFrame frame = new JFrame("Label Problem");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
JPanel componentPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel label = new JLabel("Sample Text");
label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
componentPanel.add(label);
JTabbedPane Tab = new JTabbedPane();
Tab.add("Document 1", new JPanel());
main.add(Tab);
main.add(componentPanel);
JTextArea area = new JTextArea(10, 10);
JScrollPane scroll = new JScrollPane(area);
frame.add(main);
frame.add(scroll, BorderLayout.SOUTH);
frame.setSize(450, 450);
frame.setVisible(true);
}
}
Result:
Note: I also changed the variable names to follow the java style convention: variable names should start with lower case to differenciate them from clases names, starting in upper case.
One simple approach is to set the label's horizontalAlignment to JLabel.RIGHT in the constructor.
import java.awt.*;
import javax.swing.*;
class LabelProblem {
public static void main(String[] args) {
JFrame frame = new JFrame("Label Problem");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 1));
JTabbedPane tab = new JTabbedPane();
tab.add("Document 1", new JPanel());
frame.add(tab);
JLabel label = new JLabel("Sample Text", JLabel.RIGHT);
frame.add(label);
JTextArea area = new JTextArea(10, 10);
JScrollPane scroll = new JScrollPane(area);
frame.add(scroll);
frame.pack();
frame.setSize(450, 450);
frame.setVisible(true);
}
}
I think it may be a matter of you not actually setting layouts where you imagine you're setting layouts.
You have a JPanel with a vertically oriented BoxLayout (Main) enclosing another JPanel with default layout (ComponentPanel), finally enclosing your label. The reason why your label can't be pushed to the right is because is already is pushed to the right within it's enclosing container. If you set a colored border around ComponentPanel, you'll see what I mean -- it only occupies the same amount of space as the JLabel, giving the JLabel nowhere to move.
You need to set a layout and constraints for your intermediate ComponentPanel, allowing it to horizontally fill its parent container so that the label has someplace to go.
You haven't really specified how your layout is supposed to look, but if you change the layout on Main to X_AXIS, your label will pop over to the left (as will its parent container). Without knowing what you're really trying to do, I can't say much more.
I would however, suggest you throw your BoxLayout away entirely and look into using GridBagLayout, which gives you a high level control over your UI. GridBagLayout isn't the most concise construct, but that's the price of control.
I have a problem. Now I'm working with 3 panels, mainPanel and 2 others ( btnPanel and iconPanel).
So the problem is when I push button "reset" I delete iconPanel and add it again it moves slightly to right on its own. Maybe someone can check my code where the problem?
Also I dont want to create another question so I give 2 extra questions.
Do I delete JPanel properly?
If I delete JPanel with components inside they also will be removed from memory?
P.s. Im beginner so dont judge me :)
Main.java
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Main extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Made by Mac4s");
frame.setVisible(true);
frame.setSize(310, 654);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setResizable(false);
MainScreen screenObj = new MainScreen();
screenObj.setPreferredSize(new Dimension(310, 650));
frame.add(screenObj);
}
});
}
}
MainScreen.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class MainScreen extends JPanel {
private JButton resetBtn;
private JPanel btnPanel;
private JPanel iconPanel;
public MainScreen() {
JPanel mainPanel = new JPanel(new BorderLayout());
this.setBackground(Color.BLACK);
setBtnPanelAndComp();
setIconPanelAndComp();
add(mainPanel);
}
private void setBtnPanelAndComp() {
btnPanel = new JPanel(new BorderLayout());
btnPanel.setBackground(Color.GREEN);
btnPanel.setPreferredSize(new Dimension(295, 30));
setButtons();
this.add(btnPanel, BorderLayout.NORTH);
}
private void setButtons() {
resetBtn = new JButton("Reset");
resetBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
resetIconLabel();
}
});
btnPanel.add(resetBtn, BorderLayout.WEST);
}
private void resetIconLabel() {
this.remove(iconPanel);
this.repaint();
this.revalidate();
setIconPanelAndComp();
}
private void setIconPanelAndComp() {
iconPanel = new JPanel(new BorderLayout());
iconPanel.setBackground(Color.YELLOW);
iconPanel.setPreferredSize(new Dimension(295, 580));
this.add(iconPanel, BorderLayout.SOUTH);
}
}
"the problem is when I push button "reset" I delete iconPanel and add it again it moves slightly to right on its own."
The reason this happens is because a JPanel has a FlowLayout by default. You're trying add to a BorderLayout position that is non-existent.
this.add(iconPanel, BorderLayout.SOUTH);
The FlowLayout has default gaps on the edges, so when you set the size of the frame, those gaps aren't respected. To over come this, it is also preferable to pack() the frame, instead of setSize()
The reason BorderLayout works (doesn't shift) is because preferred sizes aren't respected.
If you set the layout in the constructor to this.setLayout(new BorderLayout()); You won't have the shift.
public MainScreen() {
JPanel mainPanel = new JPanel(new BorderLayout());
this.setLayout(new BorderLayout()); <----
setBtnPanelAndComp();
setIconPanelAndComp();
add(mainPanel);
}
Notes
You should setVisible() after adding components. That's why your frame jumps when you first open it. You are setting the frame visible, then moving it around with the location, and adding components.
I've gotten stuck trying to draw on a JPanel. I've learned how to create a JFrame, a JPanel, add event handlers, do the same in applets, and some other basic GUI development. But everytime I try to draw on a JPanel using the paintComponent(Graphics g) or paint(Graphics g) methods, nothing shows up. Buttons, as well as other JComponents, show up just fine. But g.drawString, g.drawRect, etc result in a blank JFrame window.
Here is my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class Game extends JPanel {
public static void main(String[] args) {
new Game().game();
}
JPanel panel;
JButton button2;
JButton button;
public void game() {
panel = new JPanel();
button = new JButton("Ok");
panel.setLayout(new FlowLayout());
panel.add(button);
button2 = new JButton("Cancel");
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.setResizable(false);
frame.add(panel);
frame.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("hi",100,100);
g.fillRect(100,50,200,300)
}
}
The JPanel you're adding to your JFrame is a plain vanilla JPanel, not an instance of Game, your custom class that contains the paintComponent() method. YOu need to change that one line to
JPanel panel = new Game();
and you should see a difference immediately!
The instance of Game you create in main() isn't being used for anything, other than calling the game() method. You could use it, if you wanted, by doing this instead:
JPanel panel = this;
and then proceeding as before.