Palas
Palas

Reputation: 33

Efficently dealing with magic numbers in Javax.Swing Applications

I'm doing project at University right now where I have to develop a word learning/translating game where multiple clients compete to translate a words the fastest, handled by a central server. The GUI for this uses Java Swing JFrames, and to get a good looking GUI with nicely placed texts and buttons and such, you need a lot of specific numbers for distances and widths and such.

Now my Professor is VERY strict about checkstyle-violations, and she provides her own checkstyle-files, which include checks on magic numbers... Now a pretty simple code fragments with 2 methods (of 20) such as:

private void addLanguageText() {
        languageText = new JLabel();
        languageText.setText("Sprache auswählen:");
        languageText.setBounds(20, 70, 150, 30);
        frame.add(languageText);
    }

    private void addWelcomeText() {
        welcomeText = new JLabel("Willkommen zum Lernspiel!", SwingConstants.CENTER);
        welcomeText.setFont(welcomeText.getFont().deriveFont(20.0f));
        welcomeText.setBounds(0, 10, 500, 30);
        frame.add(welcomeText);
    }

Already has 8 different magic numbers, so my checkstyle warnings have about 100 entrys for magic Numbers in total.

Now it seems pretty impossible to just add 100 number constants, escpacially since they would have to have names such as WELCOME_TEXT_LEFT_BOUNDS.

What would be an efficient solution for dealing with this?

Upvotes: 1

Views: 164

Answers (2)

user11837869
user11837869

Reputation:

There's two solutions to this problem: either pull every value out to a constant (which you stated would be unreasonable), or base those values on other, more universal, constants.

For example, in order to have a welcome text in the middle of the screen, halfway down, you could write something like:

welcomeText.setBounds(0, SCREEN_HEIGHT / 2, WELCOME_TEXT_WIDTH, WELCOME_TEXT_HEIGHT);

This solution, however, is effectively similar to using a LayoutManager, albeit with a bit more customizability. There really isn't any, reasonable, way to remove all the magic numbers, but you can hide them behind math or external libraries.

Edit for clarity:

Pulling out all of the magic numbers to their own constant isn't a good solution because doing so takes a long time and heavily limits the usability of your code in non-standard situations, hence why I recommend using a LayoutManager (or a self-made variant if you want to put in extra work). To emphasize, though, a LayoutManager does not remove magic numbers, they simply hide them from view. Visual interfaces usually don't use exact fractions of the screen, for aesthetic appeal.

Upvotes: 4

tucuxi
tucuxi

Reputation: 17945

Use layout managers. This way, your interface will not only be (almost) free of magic numbers -- it will also work as expected when windows are resized, or text suddenly takes more or less space than it used to (this happens often when you translate an app from one language to another).

In particular,

  • JFrames almost always benefit from a BorderLayout
  • GridBagLayout can take care of anything (but it is a hassle to learn at first). Nested BoxLayouts are easier to learn and use.
  • Simple popup dialogues can be built very easily using JOptionPanes, which include their own layout for accept/cancel/... buttons.

Remaining magic numbers should be things like "number of columns in this dialogue" or "uniform spacing used to separate form rows", and can be given meaningful constant names.

With layouts, you never need to call setBounds directly. Several widespread IDEs have built-in graphical support for playing with layouts, so do not need to dive as deep in the documentation as it may seem. I recomment NetBean's form editor.

Upvotes: 3

Related Questions