0

I want the buttons and textfield to go in the spaces marked red in the same layout as they are in. look at the picture to understand what I mean.

update: the buttons are in the place now, but the image wont appear on the second panel

enter image description here

how can I move them to there? heres my code so far

package gasindicator;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;

public class GasIndicator extends JPanel
 {
private Image image;


GasIndicator()
{
    try
    {
        image = ImageIO.read(new URL("http://i68.tinypic.com/2ceja8i.png"));

    }
    catch (IOException ioe)
    {
        System.out.println("Unable to fetch image.");
        ioe.printStackTrace();
    }

    setLayout( new BorderLayout() );

    JLabel background = new JLabel( new ImageIcon(image) );
    background.setLayout( new FlowLayout(FlowLayout.LEFT) );
    add( background );

    JPanel buttonPanel = new JPanel( new GridLayout(0, 3, 6, 5) );
    buttonPanel.setBorder( new EmptyBorder(338, 233, 0, 0) );

    buttonPanel.setOpaque( false );


    //for (int i = 0; i < 7; i++)
    {
        JButton button = new JButton("Button");
        JButton button1 = new JButton("Button");
        JButton button2 = new JButton("Button");
        JButton button3 = new JButton("Button");
        JButton button4 = new JButton("Button");
        JButton button5 = new JButton("Button");

        button.setPreferredSize( new Dimension(160, 45) );
        buttonPanel.add(button);
        buttonPanel.add(button1);
        buttonPanel.add(button2);
        buttonPanel.add(button3);
        buttonPanel.add(button4);
        buttonPanel.add(button5);

         button.addActionListener(new Action());
    }

    background.add( buttonPanel );
}

static class Action implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            JFrame frame2 = new JFrame("Museums in London");
            frame2.setVisible(true);
            frame2.setSize(550, 650);
            JPanel panel = new JPanel();
            frame2.add(panel);
            Custom contentPane;

            // JFrame frame = new JFrame("JTextField");
            contentPane = new Custom();
            frame2.setContentPane(contentPane);

        }
    }

private static void ShowGUI()
{
    JFrame frame = new JFrame("SSCCE");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new GasIndicator());
    frame.pack();
    frame.setLocationByPlatform( true );
    frame.setVisible( true );
}

public static void main(String[] args)
{
    EventQueue.invokeLater( () -> ShowGUI() );
/*
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            createAndShowGUI();
        }
    });
*/
}

class Custom extends JPanel {

public BufferedImage image;

public Custom() {
    try {

        image = ImageIO.read(new URL 
("http://www.destination360.com/europe/uk/images/s/museums.jpg"));
    } catch (IOException ioe) {
        System.out.println("Unable to fetch image.");
        ioe.printStackTrace();
    }
}

public Dimension getPreferredSize() {
    return (new Dimension(image.getWidth(), image.getHeight()));
}

public void paintComponent(Graphics x) {
    super.paintComponent(x);
    x.drawImage(image, 10, 10, this);
}
  }
}
  • 1
    panel.setLayout(null); – ControlAltDel Mar 03 '17 at 19:44
  • 3
    Others here will tell you setting the layout to null is bad design and that you should learn to use different LayoutManagers to do this. – ControlAltDel Mar 03 '17 at 19:45
  • where do I put that? and how exactly will that move all the buttons together to the desired location? – Natalie McKnight Mar 03 '17 at 19:46
  • 1
    99.9% of the time, when you think you need a `null` layout, you don't. Layout managers do a lot of important work which goes beyond just positioning the components, the entire API is based around the interaction of the layout managers when the UI changes in some way. There are also a lot of fiddly calculations which need to be made when it comes to font metrics and different aspects of the hardware – MadProgrammer Mar 03 '17 at 22:07
  • [Here's at least one example of why null layouts fail](http://stackoverflow.com/questions/33249871/java-setting-layout-to-null/33249927#33249927). [More of disscusion on why they should be avoided](http://stackoverflow.com/questions/21242626/whats-wrong-with-the-null-layout-in-java/21242823#21242823) – MadProgrammer Mar 03 '17 at 22:09
  • If your requirements are so complicated that the existing inbuilt layouts or 3rd party layouts don't work, then it might be time to roll your own, [for example](http://stackoverflow.com/questions/15347293/making-a-button-java/15347407#15347407) or you could try some additional trickery with some the properties of the layouts themselves, [for example](http://stackoverflow.com/questions/27974966/moving-jpasswordfield-to-absolute-position/27975101#27975101) – MadProgrammer Mar 03 '17 at 22:10
  • And if your not convinced at the power of layout managers, you could take a look at [this custom, purpose built layout implementation](http://stackoverflow.com/questions/22394845/space-button-size-on-my-layout-keyboard-wont-resize/22395483#22395483) - not all layout managers need to be massivly flexibile, some can be built for a single purpose – MadProgrammer Mar 03 '17 at 22:12
  • One thing I would suggest is focus less on the "absolute" position and more on the "relationship" between the objects, this will provide you with a much more flexible solution – MadProgrammer Mar 03 '17 at 22:14
  • @MadProgrammer thanks for the help but I've got the buttons in the right places however I'm having a small error when trying to make an image showup. if you don't mind running my code above and trying to see if you can figure out the problem? – Natalie McKnight Mar 03 '17 at 22:14
  • @NatalieMcKnight It mostly works okay for me – MadProgrammer Mar 03 '17 at 22:20
  • @MadProgrammer when you click on the button and a new page opens, does that page include a background image? – Natalie McKnight Mar 03 '17 at 22:21
  • scratch that I've fixed it. – Natalie McKnight Mar 03 '17 at 22:27
  • @NatalieMcKnight Eventually, there is a noticeable lag, which you might be able to use a `SwingWorker` to help prevent blocking the EDT until the image has fully loaded and present a "loading" message – MadProgrammer Mar 03 '17 at 22:37

2 Answers2

4

Simple example to demonstrate the concept of using a layout manager with a Border. The size of the buttons has also been tweaked to the size of the buttons in the image:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;

public class SSCCE extends JPanel
{
    private Image image;

    SSCCE()
    {
        try
        {
            image = ImageIO.read(new URL("http://i68.tinypic.com/2ceja8i.png"));

        }
        catch (IOException ioe)
        {
            System.out.println("Unable to fetch image.");
            ioe.printStackTrace();
        }

        setLayout( new BorderLayout() );

        JLabel background = new JLabel( new ImageIcon(image) );
        background.setLayout( new FlowLayout(FlowLayout.LEFT) );
        add( background );

        JPanel buttonPanel = new JPanel( new GridLayout(0, 3, 6, 5) );
        buttonPanel.setBorder( new EmptyBorder(338, 233, 0, 0) );

        buttonPanel.setOpaque( false );

        for (int i = 0; i < 6; i++)
        {
            JButton button = new JButton("Button " + i);
            button.setPreferredSize( new Dimension(160, 45) );
            buttonPanel.add(button);
        }

        background.add( buttonPanel );
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

Yes, there is still some tweaking of the values. But it is easier to adjust the location of the entire panel with one EmptyBorder and all the buttons move at the same time than it is to adjust the location of each button individually.

Note: Don't use the JLabel to display the image as the components will shift if the frame is resized. Instead use your custom panel to paint the image.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • perfect thank you! however, there is one thing I'm confused about. how can I name all six buttons different names? also each button opens a new panel using an actionlistener on my code, can you do 1 actionlistener for me using this code then i'll be able to see how you did it and do the rest on my own – Natalie McKnight Mar 03 '17 at 21:39
  • 1
    @NatalieMcKnight, You don't need the loop to create the buttons. This is just a short example to demonstrate the concept. In your code you create the buttons individually and add the ActionListeners to each button individually. Also don't forget to read the "note" I added. – camickr Mar 03 '17 at 21:45
  • yeah noted. theres just another small error I'm getting, when i click on the button a new panel opens which is supposed to contain a background image but it wont show up, can you run my code and see if you can figure out why? i updated it above – Natalie McKnight Mar 03 '17 at 22:05
-3

The problem here is that your panel has the standart Layoutmanager set onto it. Try disable it with

contentPane.setLayout(null);

Then you can move the buttons around like you want with button.setBountds(x,y,w,h);

I always draw directly on the Frame, not using a custom panel like you do, but I see that there are use cases where this would be the better way.

If you write

new JFrame.getContentPane().setLayout(null);

your frame gets the default pane and still has it's layout set to null.

The difference is you can add directly to the frame instead of using a panel where you drop your stuff on.

frame.add(new Button().setBounds(x,y,w,h));

Try out this version of the code I tried to debugg:

Custom1 contentPane;


//at first create and set the frame
JFrame frame = new JFrame("Windowname goes here");
frame.setSize(1160, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);

//next add your custom panel
contentPane = new Custom1();
frame.setContentPane(contentPane);

//better add this to the panel instead of the frame
JTextField textfield = new JTextField(20);
frame.add(textfield);

textfield.setBackground(Color.black);
textfield.setForeground(Color.white);

//you are using 2 panels with null layout here
JPanel panel = new JPanel();
panel.setSize(frame.getHeight(),frame.getWidth());      //give the panel some bounds!
panel.setOpaque(false); //unnecesary
panel.setLayout(null);
panel.setBackground(Color.BLACK);
frame.add(panel);

JButton button = new JButton("London");
JButton button1 = new JButton("Oxford");
JButton button2 = new JButton("Cambridge");

//you seemed to not have added these before
JButton button4 = new JButton("Click");
JButton button5 = new JButton("Click");
JButton button6 = new JButton("Click");

button.setBounds(60, 400, 220, 30);
button.setBackground(Color.black);
button.setForeground(Color.WHITE);

button1.setBounds(x,y,w,h);                         // !!!! <------
button1.setBackground(Color.black);
button1.setForeground(Color.WHITE);

button2.setBounds(x,y,w,h);                         // !!!! <------
button2.setBackground(Color.black);
button2.setForeground(Color.WHITE);

button4.setBounds(80, 50, 100, 30);
button5.setBounds(x,y,w,h);                         // !!!! <------
button6.setBounds(x,y,w,h);                         // !!!! <------

panel.add(button);
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
panel.add(button6);

//SETVISIBLE ALWAYS GOES LAST
frame.setVisible(true);

I patched your code and wrote some comments in it. I marked the spots where you need to set the bounds for the buttons with !!!!<----,
you seemed to have made this for button4 but not for the other ones. Also you should get a better structure in your code, I don't want to insult you but I would call this "spaghetti code". There are aswell some things that where a problem, for example you seemed to not have added the buttons at all but they where present in your picture...

Let me know if it would work or not after playing around with the bounds value and investigating for eventual mistakes in the code. Also if you sent me the whole project I could watch over it, but better try it yourself, it won't give you anything if someone else made your work.

Good luck and happy coding ( ͡° ͜ʖ ͡°)

clockw0rk
  • 576
  • 5
  • 26
  • can you add that to my code? when I add it. it removes all the buttons as if they are not there – Natalie McKnight Mar 03 '17 at 19:55
  • 3
    (1-) Don't use a null layout. Use a GridLayout or GridBagLayout on the panel containing your buttons. – camickr Mar 03 '17 at 20:10
  • @camickr I'm using the grid layout but that doesn't move all the buttons over the location I want them in – Natalie McKnight Mar 03 '17 at 20:12
  • @clockw0rk anything? – Natalie McKnight Mar 03 '17 at 20:12
  • @camickr you are basicly right, but what if you have a custom layout that you created with let's say a photoshop file for the background in mind? then you won't get far with a fixed layoutmanager i guess. and op is seemingly doing exactly that – clockw0rk Mar 03 '17 at 20:29
  • 1
    `....then you won't get far with a fixed layoutmanager` - of course you can. You can nest panels. You can provide horizontal/vertical gaps between panels. You can use Borders on panels. It is far easier to all components to a panel with a layout manager and then adjust the location of the panel using the above techniques, then it is to adjust the location of each independent button. – camickr Mar 03 '17 at 20:34
  • @clockw0rk I pasted your code and set various bounds but all the buttons stayed in the same positions as they were before. also the buttons you saw on the background aren't buttons they are part of the picture for me to navigate where I want the real buttons to go. – Natalie McKnight Mar 03 '17 at 20:36
  • @camickr can you show me how to do that with my code? – Natalie McKnight Mar 03 '17 at 20:37
  • ok, sorry if i insulted you in any way. you surely can achieve this goal by nesting panels and working with gaps and stuff. i just tried to fix op's code here, and personally i never worked with layout managers since i always believed i knew what i was doing. maybe you could pin out what exactly makes null layouts such a bad thing? – clockw0rk Mar 03 '17 at 20:38
  • @ Natalie McKnight Could you show us where Custom1 is derived from? – clockw0rk Mar 03 '17 at 20:40
  • @clockw0rk I tried but it doesn't change the button layout, it just removes all of them. can you combine my code with his so I can try if it works? I'm not really sure how, so if you can do that I would be grateful – Natalie McKnight Mar 03 '17 at 21:11
  • His example works perfectly fine on my mashine just download it and compile it. here take a look on this (editing is really a pain for me right now) [screenshot](http://www.directupload.net/file/d/4649/8fx8c3xm_png.htm) – clockw0rk Mar 03 '17 at 21:22
  • see above answere – clockw0rk Mar 03 '17 at 21:33
  • 2
    *"maybe you could pin out what exactly makes null layouts such a bad thing?"* Sure! [null layout is evil](http://www.leepoint.net/GUI/layouts/nulllayout.html), also the answers in [this question](http://stackoverflow.com/questions/6592468/why-is-it-frowned-upon-to-use-a-null-layout-in-swing) and [this example](http://stackoverflow.com/questions/42520492/jtable-not-showing-up-on-jframe-java/42521097#42521097). So, that's why you should use [layout managers](https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) as suggested above by @camickr (I downvoted for the same reason as him) – Frakcool Mar 03 '17 at 21:49
  • @ Frakcool Thank you very much. I think I deserve the down vote ^^ Under the line it is highly dangerous when building applications that will run on different machines and java versions by means of usability and look/feel. Are there ever times you could mindlessly use the null layout then? I could imagine writing a custom application running on a single machine only, but is there a reason they implemented it in the first place? Tanks for making that clear mate – clockw0rk Mar 03 '17 at 21:59
  • I didn't get notified because you added a space before `@` *"I think I deserve the down vote"* (If I were you I would delete the answer). *"Are there ever times you could mindlessly use the null layout then?"* yes, but they are just a phew, like component animation (as explained by MadProgrammer on the comments of [this answer](http://stackoverflow.com/a/42404808/2180785) and shown in his own answer in the same question. – Frakcool Mar 04 '17 at 00:28
  • *"I could imagine writing a custom application running on a single machine only"* What if you break your PC and need that on another new one? It would look awful. I'm not an expert at all, but someone else might have some better examples. Just Google for them maybe – Frakcool Mar 04 '17 at 00:30