0

I'm trying to create a binary clock in Java using swing. I encountered a problem on very beginning, where last element of label array is always appearing on the 0 x axis position and in the middle of y axis.

I don't want to use any layout menager since i want few circle images on my Panel.

Here's my code so far:

import javax.swing.*;

@SuppressWarnings("serial")
public class MainFrame extends JFrame {

public MainFrame()
{
    setLayout(null);
    JFrame frame = new JFrame("Binary Clock");
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.setSize(600,400);
    frame.setResizable(false);

    JLabel label[] = new JLabel[5];
    for(int i = 0; i < 5; i++)
    {
        label[i] = new JLabel();
        label[i].setLocation(i * 10, i * 10);
        label[i].setSize(30, 10);
        label[i].setText("TEST");
        frame.add(label[i]);
    }       
}

public static void main(String[] args)
{
    new MainFrame();
}
}

i found similar question here:

setLocation of Label

but there is no answer how to do it without layout manager.

I Tried resizing and stuff, but only setText() can do any difference, nothing besides that works.

Thank you!

Community
  • 1
  • 1
tomiQrds
  • 95
  • 10
  • 1
    Make use of an appropriate layout manager – MadProgrammer Feb 16 '15 at 20:38
  • *"I don't want to use any layout menager"* - This is your first problem and it will continue to give your problems – MadProgrammer Feb 16 '15 at 20:56
  • maybe so, im a beginner tho. My problem is already fixed so it's all good now – tomiQrds Feb 16 '15 at 21:01
  • 1
    @tomiQrds I wouldn't say that your problem is fixed, but it was moved farther from you. There is still chance that it will kick you in future when you will want to add new things to your app. I would listen to MadProgrammer advice. – Pshemo Feb 16 '15 at 21:04
  • @tomiQrds Until you discover that it doesn't work on your friend's or schools computer or it doesn't look right with some other font or your decide you want to start using it with other components and ask another question because you can't solve it, because you used the wrong approach. `null` layouts only cause more problems. Best to learn how to deal without them now – MadProgrammer Feb 16 '15 at 21:06
  • Thank you very much for all input and responses, i really appreciate that. So far it's all running good, but if i stumble across another issue with that i will definetly look into layouts managers. I'm doing that little project for kicks, i'm not into java or swing so i won't use that skill in the future. – tomiQrds Feb 16 '15 at 21:36

3 Answers3

2

Pshemo's answer provides the answer as to why you're getting the odd behavior with the last label added, but I've marked up the code with a couple enhancements as well.

  1. Remove the extends JFrame, this is rarely a good idea and you already saw why using an instance of a JFrame within a class that is a JFrame can cause...

  2. Set the layout of the frame instance to null (rather than that of this) that you have originally. Note: Use of a layout manager is the preferred method to creating Swing UI's, and is generally discouraged to set this to null

  3. You don't need the array of labels (unless you plan on using them later), you can just use the loop to add what you want.

  4. Make the frame visible last

Then you have:

import javax.swing.*;

@SuppressWarnings("serial")
public class MainFrame {

    public MainFrame()
    {
        JFrame frame = new JFrame("Binary Clock");
        frame.setLayout(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600,400);
        frame.setResizable(false);

        for(int i = 0; i < 5; i++)
        {
            JLabel label = new JLabel();
            label.setLocation(i * 10, i * 10);
            label.setSize(30, 10);
            label.setText("TEST");
            frame.add(label);
        }

        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        new MainFrame();
    }
}
Ryan J
  • 8,275
  • 3
  • 25
  • 28
  • Partially related: [Extends JFrame vs. creating it inside the the program](http://stackoverflow.com/questions/22003802/extends-jframe-vs-creating-it-inside-the-the-program/22003885#22003885), consider including it in your answer. – Pshemo Feb 16 '15 at 19:00
  • Null layouts are NEVER the answer, the op could achieve he same thing with a GridLayout or GridBagLayout and get better cross platform support – MadProgrammer Feb 16 '15 at 20:35
  • @MadProgrammer the OP specifically requested a solution that didn't require a layout manager, so I gave him one. – Ryan J Feb 16 '15 at 20:45
  • The OP might like a flying pig to, but there are right ways to do something and wrong was to do something and `null` layouts are the wrong way regardless of what the OP might think they want – MadProgrammer Feb 16 '15 at 20:54
  • @MadProgrammer Ok, but imparting a "the way you want to do it is wrong" mentality isn't going to help the OP understand _why_ he's getting a problem, and how to avoid it in the future. I'm not disputing what you say, I just don't think it specifically warrants a downvote, because it's not relevant to the question. Updated anyways. – Ryan J Feb 16 '15 at 20:58
  • As professionals, we should always be providing professional advice. `null` layouts are not a suitable solution and should be avoid. Seriously, in 15+ years of commercial development, I've never had a need to use a `null` layout, I've written a few layout managers to solve particular problems, but never had to resort to `null` layouts. If the OP wants to shot themselves in the foot, that's there problem, but we shouldn't load and hand them the gun to do it. There is more to answering a question then simply solving the immediate problem - IMHO – MadProgrammer Feb 16 '15 at 21:03
  • @MadProgrammer again, I'm not disagreeing with you. If you want someone to understand a problem, simply telling them "this is how you _should_ do it" and not providing the full background does them no good. We keep the answers to questions on SO relevant to the question being asked, and we see lots of questions that have very simple answers to professional programmers. So, when we answer questions, we do so, _in the best possible way_ to solve the problem at hand, and leave the _it could be done better_ to the asker to figure out. – Ryan J Feb 16 '15 at 21:08
  • Awesome, so you've handed the OP a loaded gun and we'll just need to waste more time later cleaning up your mess... – MadProgrammer Feb 16 '15 at 21:31
  • @MadProgrammer dude, chill out. Don't be so melodramatic. I already updated the answer to account for your points. – Ryan J Feb 16 '15 at 23:17
  • Forgive my pig headerness, I've spent the last six years fixing an application which was full of `null` layouts and `setPreferredSize`s written by a junior J2EE developer, so when I see `null` layouts, my sanity breaks...more... – MadProgrammer Feb 16 '15 at 23:48
1

I am not Swing specialist so I don't know what consequences will give you null layout manager but from what I remember it is nothing good so consider using proper layout manager instead of null.
Anyway it seems that your problem is caused by fact that you set your null layout in currently initialized by constructor this instance, rather than instance from form regerence.

So instead of

setLayout(null);// represents this.setLayout(..), not frame.setLayout(..)
JFrame frame = new JFrame("Binary Clock");

use

JFrame frame = new JFrame("Binary Clock");
frame.setLayout(null);

I am also not sure why your class extends JFrame. Your code doesn't actually look like it needs any of inherited features from JFrame.

Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • I borrowed from your answer to write one of my own, +1 – Ryan J Feb 16 '15 at 18:57
  • 1
    Null layouts are NEVER the answer, the op could achieve he same thing with a GridLayout or GridBagLayout and get better cross platform support – MadProgrammer Feb 16 '15 at 20:36
  • @MadProgrammer I believe you, but I can't agree with downvote reasoning. Main problem in this question is that OP is using `setLayout` on `this` instead on `form`. Even if OP would use proper layout manager as argument of this method problem would stay because it would not affect instance from `form` reference, which I tried to explain in my answer. Just because I didn't point other potential problems doesn't make my answer wrong (at least IMO). – Pshemo Feb 16 '15 at 20:45
  • I agree you found the symptom of there problem, but providing bad advice is still providing bad advice. `null` layouts in any form are ill advised and will cause no end of issues regardless – MadProgrammer Feb 16 '15 at 20:57
  • I didn't advice to use `null`, at least not explicitly. But OK since I also didn't say it was bad approach (I may not know or remember it) we can assume that I approved it. In that case, yes I am guilty and I accept this down-vote. I will also not delete this answer so others could read your comment and avoid `null` in future. – Pshemo Feb 16 '15 at 21:06
1

I don't want to use any layout menager since i want few circle images on my Panel.

Swing was designed at the core to use layout managers, it how it's update process works and how it deals with the difference in rendering pipelines across multiple platforms. Sure, you can try and do without it, but in the end, you'd simply reinvent the wheel as you try and compensate for all the little niggly issues that are created while trying to do without it.

The following simply uses a GridBagLayout, which provides me with the ability to supply gridx/y positions to the components (and other nice things)

Clock

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BinaryClock {

    public static void main(String[] args) {
        new BinaryClock();
    }

    public BinaryClock() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            // Hour column
            gbc.gridx = 0;
            addColumn(2, gbc);
            gbc.gridx = 1;
            addColumn(4, gbc);
            // Minute column
            gbc.gridx = 3;
            addColumn(3, gbc);
            gbc.gridx = 4;
            addColumn(4, gbc);
            // Minute column
            gbc.gridx = 6;
            addColumn(3, gbc);
            gbc.gridx = 7;
            addColumn(4, gbc);

            gbc.gridx = 2;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.VERTICAL;
            gbc.gridheight = GridBagConstraints.REMAINDER;
            add(new JSeparator(JSeparator.VERTICAL), gbc);

            gbc.gridx = 5;
            add(new JSeparator(JSeparator.VERTICAL), gbc);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void addColumn(int count, GridBagConstraints gbc) {
            for (int index = 0; index < count; index++) {
                gbc.gridy = 3 - index;
                add(new Dot(), gbc);
            }
        }

    }

    public class Dot extends JPanel {

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setColor(Color.DARK_GRAY);
            g2d.fillOval(0, 0, getWidth() - 1, getHeight() - 1);
            g2d.dispose();
        }

    }

}

This now frees you up to worry about how to make the clock update without need to continuously try and fix issues in the layout

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366