I was wondering why my button does not show up on the panel until AFTER I hover my mouse over where it would be? It also disappears again if I resize the window. The MainMenuScreen is just an image I use as my background image.
//MainMenu setup
JPanel card2 = new JPanel();
card2.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2,2,2,2);
gbc.anchor = GridBagConstraints.CENTER;
MainMenuScreen mms = new MainMenuScreen();
mms.setLayout(new FlowLayout());
card2.add(mms);
card2.add(menuButton1, gbc);
Here is how I setup by background image.
public class MainMenuScreen extends JPanel{
private static final long serialVersionUID = 1L;
private BufferedImage background;
public MainMenuScreen() {
try {
background = ImageIO.read(new File("M&M Arcade.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
int x = (getWidth() - background.getWidth());
int y = (getHeight() - background.getHeight());
g.drawImage(background, x, y, this);
}
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(Color.white);
}
}
The JButton doesn't show up beacuse you are using the same GridBagConstraints values for your MainMenuScreen component and your JButton menuButton1, i.e. they exist at the same location. Once the values of gbc are adjusted, the button will appear. Also better to consistently use the correct overloaded method of add when adding to a container with GridBagLayout.
Edit:
There have been numerous discussions on how to implement background images on JPanel containers. A notable one is Background Panel.
Related
So I'm using Swing and trying to use a JTabbedPane to encompass several JPanels with JScrollPanes to scroll through a list of JPanels. The issue that arises is whenever I change tabs, among other things, the custom border function I have in the JPanels inside the scroll pane results in the components painting over the top of the JTabbedPane header and I have no idea of how to fix this problem: AbstractBorder paints over JTabbedPane header. I have provided code that mimics what I'm trying to do below. To replicate the issue, scroll down some on one tab until one of the outlined panels is halfway visible at the top. Then, switch to a different tab and then back. Then, scroll some more and the issue will present itself at the top of the JTabbedPane
public class Example extends JFrame {
private final JTabbedPane tabbedPane;
public Example() {
setTitle("MIN Example");
setSize(600, 700);
setLayout(new BorderLayout());
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.BLACK);
setExtendedState(JFrame.MAXIMIZED_BOTH);
tabbedPane = new JTabbedPane();
tabbedPane.setBorder(BorderFactory.createEmptyBorder());
tabbedPane.setFocusable(false);
add(tabbedPane, BorderLayout.CENTER);
createTabs();
setVisible(true);
}
private void createTabs() {
// Get the list of guilds
List<String> tabs = new ArrayList<>(Arrays.asList("Tab 1", "Tab 2", "Tab 3"));
// Iterate through the tabs and create the tab
for (String tab : tabs) {
// Initialize the list JPanel and formatting
JPanel panelList = new JPanel();
panelList.setLayout(new GridBagLayout());
// House the list panel inside a JScrollPane
JScrollPane listScroll = new JScrollPane(panelList);
listScroll.setBorder(BorderFactory.createEmptyBorder());
// Create tab and formatting
tabbedPane.addTab(tab, listScroll);
populateList(panelList);
}
}
private void populateList(JPanel tab) {
// Create GBC for formatting
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
// Remove all components from the JPanel
tab.removeAll();
// Add filler JPanel
JPanel filler = new JPanel();
filler.setOpaque(false);
tab.add(filler, gbc);
// Update GBC constraints
gbc.insets = new Insets(10, 10, 0, 10);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = GridBagConstraints.RELATIVE;
// Go through the tabs and add JPanels
for (int i = 10; i >= 0; i--) {
JPanel tempPanel = new JPanel();
tempPanel.setBorder(new RoundedBorder(Color.BLACK, 6, 16));
tab.add(tempPanel, gbc, 0);
tempPanel.setPreferredSize(new Dimension(0, 100));
}
// Refresh the console to display updated lists
validate();
repaint();
}
}
public class RoundedBorder extends AbstractBorder {
private final Color color;
private final int thickness;
private final int radii;
private final Insets insets;
private final BasicStroke stroke;
private final int strokePad;
RenderingHints hints;
/**
* Creates the rounded border
*
* #param color The color of the border outline
* #param thickness The thickness of the border outline
* #param radii The radius of the rounded border
*/
public RoundedBorder(Color color, int thickness, int radii) {
this.thickness = thickness;
this.radii = radii;
this.color = color;
stroke = new BasicStroke(thickness);
strokePad = thickness / 2;
hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int pad = radii + strokePad;
int bottomPad = pad + strokePad;
insets = new Insets(pad, pad, bottomPad, pad);
}
#Override
public Insets getBorderInsets(Component c) {
return insets;
}
#Override
public Insets getBorderInsets(Component c, Insets insets) {
return getBorderInsets(c);
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g;
int bottomLineY = height - thickness;
RoundRectangle2D.Double bubble = new RoundRectangle2D.Double(strokePad, strokePad, width - thickness, bottomLineY, radii, radii);
Area area = new Area(bubble);
g2.setRenderingHints(hints);
// Paint the background color of the parent
Component parent = c.getParent();
if (parent != null) {
Color background = parent.getBackground();
Rectangle rect = new Rectangle(0,0,width, height);
Area borderRegion = new Area(rect);
borderRegion.subtract(area);
g2.setClip(borderRegion);
g2.setColor(background);
g2.fillRect(0, 0, width, height);
g2.setClip(null);
}
g2.setColor(color);
g2.setStroke(stroke);
g2.draw(area);
}
}
The only things I have tried to do to fix this issue was changing the order of adding the JTabbedPane (Add before the tabs were populated with panels) to no avail. Help would be greatly appreciated, thank you.
In the future, an MRE should include:
the import statements
the main() method
In the original code the "clip" of the Graphics is being set to null so the entire Rectangle of the panel appears to be painted.
I modified the painting of the parent to use a separate Graphics object so the original "clip" area is not affected:
// Paint the background color of the parent
Component parent = c.getParent();
if (parent != null) {
Graphics2D g2d = (Graphics2D)g2.create();
Color background = parent.getBackground();
//Rectangle rect = new Rectangle(0, 0, width, height);
Rectangle rect = g2d.getClip().getBounds();
Area borderRegion = new Area(rect);
borderRegion.subtract(area);
g2d.setClip(borderRegion);
g2d.setColor(background);
g2d.fillRect(0, 0, width, height);
g2d.dispose();
}
I have a class that extends JFrame and I would like to add two JPanels to that JFrame: a text panel and a graphics panel. My text panel is a panel containing a label with text. My graphics panel will contain a graph (created using 2DGraphics). I'm adding the graphic panel to the left side (0,0) and the text panel to right side (1,0) using a gridbaglayout method. However, the graphic panel won't show up in the frame. I have tried numerous methods to try to get the panel to show up with no success.
import java.awt.*;
import javax.swing.*;
public class GraphicsTest extends JFrame {
private final JPanel textPanel;
private final JLabel textLabel;
public GraphicsTest() {
textPanel = new JPanel(new BorderLayout());
textLabel = new JLabel("Home label");
this.setBounds(180, 112, 1080, 675);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridBagLayout());
textPanel.add(textLabel, BorderLayout.NORTH);
addComponent(this, new GraphicPanel(), 0, 0, 1, 1, GridBagConstraints.CENTER);
addComponent(this, textPanel, 1, 0, 1, 1, GridBagConstraints.CENTER);
this.setVisible(true);
}
public class GraphicPanel extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void paintComponents(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
// drawing lots of shapes and lines, removed for readibility
}
}
public void addComponent(JFrame frame, JComponent component, int x, int y, int width, int height, int align) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = x;
c.gridy = y;
c.gridwidth = width;
c.gridheight = height;
c.weightx = 100.0;
c.weighty = 100.0;
c.insets = new Insets(5, 0, 5, 0);
c.anchor = align;
c.fill = GridBagConstraints.NONE;
frame.add(component, c);
}
public static void main(String[] args) {
GraphicsTest gui = new GraphicsTest();
}
}
Works fine for me when I use a size like (200, 200).
GridbagLayout works such that if a component can't be displayed at its preferred size, then it will be displayed at its minimum size, which would be (0, 0).
So whether (700, 700) works will depend on your screen resolution. It also works at (700, 600) for my screen.
I question if you want to use a GridBadLayout. Maybe just use a BorderLayout. The custom painting panel would go in the CENTER so it will grow/shrink as the frame size changes. The other panel would go to the LINE_END, so it will remain at a fixed size.
JButtons had the default size and I can't change it. I was try with setSize and it don't do anything. When I click on some of JButtons picture will be set and the JButtons will get size of the picture. I want to set size of JButton to be the same like the size of JButton when I click on it(JButton with picture)
btn=new JButton[9];
j=0;
for (i = 0; i <btn.length; i++) {
btn[i] = new JButton("");
btn[i].addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if(j%2==0){
((JButton) e.getSource()).setIcon(new ImageIcon("resources/X.png"));
}else{
((JButton) e.getSource()).setIcon(new ImageIcon("resources/O.png"));
}
((JButton) e.getSource()).setEnabled(false);
j++;
}
});
}
GridBagConstraints gbc=new GridBagConstraints();
gbc.gridx=0;
gbc.gridy=0;
p2.add(btn[0],gbc);
gbc.gridx=1;
gbc.gridy=0;
p2.add(btn[1],gbc);
gbc.gridx=2;
gbc.gridy=0;
p2.add(btn[2],gbc);
.........
Probably the simplest and most reliable solution is to use a blank image which is the same size as the others as the initial image for the button
Very few layout managers allow you to directly suggest the size of a given component, in fact, the intention is to allow the component to tell the layout manager what it wants and then let the layout manager figure out if it can accomidate it.
For example...
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, 32, 32);
g2d.dispose();
GridBagConstraints gbc = new GridBagConstraints();
for (int row = 0; row < 3; row++) {
gbc.gridy = row;
for (int col = 0; col < 3; col++) {
gbc.gridx = col;
add(new JButton(new ImageIcon(img)), gbc);
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
In this example I've created my own blank image, you could do the same, but it's just as easy to load blank image, the concept is the same
I'm making the game "Who is millionaire".
This is the help panel, which let user choose one of the options such as: calling friend, asking audience, etc.
But I have a problem, the options are ellipses, which are drawn in class Help_Option extends JComponent. When I test this class Help_Option individually, it works fine. But when I add the Help_Option object into the game panel, actually a sub-panel in the frame, it just displays a line on the panel, it doesn't draw my ellipse.
This is my code:
Note: a is JFrame, I don't copy the whole method initialize(JFrame a) cos it's quite long and I don't think that the error comes from there.
/******Helper panel**********/
JPanel help_area_container = new JPanel();
help_area_container.setBorder(BorderFactory.createLineBorder(Color.BLUE, 3));
help_area_container.setLayout(new GridLayout(4,0));
JPanel voting_container = new JPanel();
JPanel calling_container = new JPanel();
JPanel half_container = new JPanel();
JPanel take_container = new JPanel();
JPanel[] all_help_container = new JPanel[]{voting_container, calling_container, half_container, take_container};
for(int i = 0; i < all_help_container.length; i++){
all_help_container[i].setBorder(BorderFactory.createLineBorder(Color.RED));
all_help_container[i].setPreferredSize(new Dimension(350, help_area_container.getPreferredSize().height/4));
}
for(int j = 0; j < all_help_container.length; j++){
help_area_container.add(all_help_container[j]);
}
Help_Option voting_option = new Help_Option(all_help_container[0].getPreferredSize().width, all_help_container[0].getPreferredSize().height);
voting_option.setPreferredSize(new Dimension(all_help_container[0].getPreferredSize().width, all_help_container[0].getPreferredSize().height));
all_help_container[0].add(voting_option);
a.add(help_area_container, BorderLayout.EAST);
/*****************************/
This is the Help_Option class:
class Help_Option extends JComponent implements MouseMotionListener{
private static int x, y;
private Ellipse2D ellipse;
private Color c = Color.BLACK;
public Help_Option(int x, int y){
Help_Option.x = x;
Help_Option.y = y;
ellipse = new Ellipse2D.Double(0, 0, x, y);
this.addMouseMotionListener(this);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
g2d.draw(ellipse);
g2d.setColor(c);
g2d.fill(ellipse);
g2d.setColor(Color.RED);
g2d.setFont(new Font("TimesRoman", Font.BOLD, 20));
g2d.drawString("Here I am", 250, 100);
}
public void setColor(Color c){
this.c = c;
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
if(ellipse.contains(e.getX(), e.getY())){
setColor(Color.GREEN);
repaint();
}else{
setColor(Color.BLACK);
repaint();
}
}
}
And this is the class that i used to test Help_Option class:
public class Help extends JFrame{
public static void main(String [] agrs){
Help h = new Help();
h.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
h.init();
}
public void init(){
this.setLayout(new FlowLayout());
this.setSize(2000, 1000);
JPanel a = new JPanel();
a.setPreferredSize(new Dimension((int)a.getSize().width/3, (int)a.getSize().height/2));
a.setBorder(BorderFactory.createLineBorder(Color.yellow, 3));
Help_Option k = new Help_Option(a.getPreferredSize().width, a.getPreferredSize().height/2);
k.setPreferredSize(new Dimension(a.getPreferredSize().width, a.getPreferredSize().height));
a.add(k);
this.add(a);
this.setVisible(true);
}
}
EDIT
This is the link to my classes, please take a look at them. The error is described above.
It is that you haven't set values for your first couple of JPanels and they are returning preferred sizes of 0. Dimensions of 0,0
So you should add values to the JPanels there.
public static void main(String[] args) {
JPanel help_area_container = new JPanel();
help_area_container.setBorder(BorderFactory.createLineBorder(
Color.BLUE, 3));
help_area_container.setLayout(new GridLayout(4, 0));
//Should have set sizes below
JPanel voting_container = new JPanel();
//voting_container.setSize(50,50);
JPanel calling_container = new JPanel();
JPanel half_container = new JPanel();
JPanel take_container = new JPanel();
JPanel[] all_help_container = new JPanel[] { voting_container,
calling_container, half_container, take_container };
for (int i = 0; i < all_help_container.length; i++) {
all_help_container[i].setBorder(BorderFactory
.createLineBorder(Color.RED));
all_help_container[i].setPreferredSize(new Dimension(350,
help_area_container.getPreferredSize().height / 4));
}
for (int i = 0; i < all_help_container.length; i++) {
System.out.println(all_help_container[i].getSize());
}
}
// where you can change the size
all_help_container[0].setSize(50, 50);
System.out.println("----");
for (int i = 0; i < all_help_container.length; i++) {
System.out.println(all_help_container[i].getSize());
}
}
Hopefully this will help you with the sizing of your GUI.
You will have to adjust the different panels to suit your needs. As I'm guessing that this panels will contain some other stuff in them.
You may want to create custom JPanels for each of these, so that you can easily check if they are the right size.
public class VotingPanel extends JPanel {
public VotingPanel(){
//All your variables such as size and color schemes
}
}
This question is related to my previous question How to generate Cartesian Coordinate (x,y) from GridBaglayout?
I have successfully get the coordinate of each pictures, however when I checked the coordinate through (System.out.println) and the placement of the images on the screen, it seems to be wrong. e.g. if on the screen it was obvious that the x point of the first picture is on cell 2 which is on coordinate of 20, but the program shows x=1.
Here is part of the code:
public Grid (){
setPreferredSize(new Dimension(600,600));
....
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.weightx = 1d;
gc.weighty = 1d;
gc.insets = new Insets(0, 0, 0, 0);//top, left, bottom, and right
gc.fill = GridBagConstraints.BOTH;
JLabel[][] label = new JLabel[ROWS][COLS];
Random rand = new Random();
// fill the panel with labels
for (int i=0;i<IMAGES;i++){
ImageIcon icon = createImageIcon("myPics.jpg");
int r, c;
do{
//pick random cell which is empty
r = (int)Math.floor(Math.random() * ROWS);
c = (int)Math.floor(Math.random() * COLS);
} while (label[r][c]!=null);
//randomly scale the images
int x = rand.nextInt(50)+30;
int y = rand.nextInt(50)+30;
Image image = icon.getImage().getScaledInstance(x,y, Image.SCALE_SMOOTH);
icon.setImage(image);
JLabel lbl = new JLabel(icon); // Instantiate GUI components
gc.gridx = r;
gc.gridy = c;
add(lbl, gc); //add(component, constraintObj);
label[r][c] = lbl;
}
I checked the coordinate through this code:
Component[] components = getComponents();
for (Component component : components) {
System.out.println(component.getBounds());
}
You can use SwingUtilities convertPointToScreen() and convertPointFromScreen() to convert between screen and component coordinates.
Addendum: Here's a simple example I used when trying to understand how components move and resize under the influence of a layout manager.
public class MyPanel extends JPanel {
public MyPanel() {
super(new GridLayout(4, 4));
for (int i = 0; i < 16; i++) {
JPanel panel = new JPanel(new GridLayout());
panel.add(new CenterLabel());
this.add(panel);
}
}
private static void create() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
create();
}
});
}
private static class CenterLabel extends JLabel {
public CenterLabel() {
this.setHorizontalAlignment(JLabel.CENTER);
this.setVerticalAlignment(JLabel.CENTER);
this.setOpaque(true);
this.setBackground(Color.lightGray);
this.setBorder(BorderFactory.createLineBorder(Color.blue));
this.setPreferredSize(new Dimension(160, 100));
this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
int w = e.getComponent().getWidth();
int h = e.getComponent().getHeight();
CenterLabel.this.setText("[" + w/2 + "\u253C" + h/2 + "]");
}
});
}
}
}
if on the screen it was obvious that
the x point of the first picture is on
cell 2 which is on coordinate of 20,
but the program shows x=1.
The first image will have x/y coordinates of 0/0. The second images will have coordinates of 1/0. The X/Y values of offset from 0. Is that what you are talking about?
Or is your listener added to the image not the panel in which case you need to convert the image coordinates to the panel coordinates. Check our the SwingUtilities class for methods to do this.
If you need more help post your SSCCE.