0

I am working on a java gui application using a Canvas on a JFrame. I tried to draw thin rects on a Jframe and noticed, that they not allways have the same width displayed.

This is the rusult of a test class I wrote. The left side is drawn by using fillRect()with the width of 1 and the right side is drawn using drawLine.

canvas

This is the code of my test class.

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;

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

    public test(){
        JWindow frame = new JWindow();
        frame.setSize(500,500);
        frame.setLocation(200,200);

        Canvas c = new Canvas();
        frame.add(c);

        frame.setVisible(true);

        new Thread(() -> {
            while(true) {
                BufferStrategy bs = c.getBufferStrategy();

                if (bs == null) {
                    c.createBufferStrategy(2);
                    bs = c.getBufferStrategy();
                }

                Graphics g = bs.getDrawGraphics();
                Graphics2D g2 = (Graphics2D) g;

                g2.setColor(Color.black);

                for(int i = 0; i < 50; i++){
                    if(i % 4 == 0){
                        g2.fillRect(20 + i, 50, 1, 100);
                    }
                    else if(i % 4 == 1){
                        g2.fillRect(20 + i, 150, 1, 100);
                    }
                    else if(i % 4 == 2){
                        g2.fillRect(20 + i, 250, 1, 100);
                    }
                    else{
                        g2.fillRect(20 + i, 350, 1, 100);
                    }
                }

                for(int i = 0; i < 50; i++){
                    if(i % 4 == 0){
                        g2.drawLine(100 + i, 50, 100 + i, 150);
                    }
                    else if(i % 4 == 1){
                        g2.drawLine(100 + i, 150, 100 + i, 250);
                    }
                    else if(i % 4 == 2){
                        g2.drawLine(100 + i, 250, 100 + i, 350);
                    }
                    else{
                        g2.drawLine(100 + i, 350, 100 + i, 450);
                    }
                }

                g.dispose();
                bs.show();
            }
        }).start();
    }
}

Does someone know how that works or maby even a way to fix that?

carlos.gmz
  • 100
  • 8
  • For me, both sides look pretty much the same... https://paste.pics/f94f6b3dcc47c6da97a6cf83e61878a6 – MonsterDruide1 Feb 07 '21 at 17:21
  • oh, thats weird, maby it has to do with my screen resolution? I think I have a smaller display than 1920 * 1080, wich is my resolution in windows, but that still not explains the difference between bot sides – carlos.gmz Feb 07 '21 at 17:30
  • For your information, you don't need a `java.awt.Canvas`. You can also draw on a `javax.swing.JPanel`. Refer to [Performing Custom Painting](https://docs.oracle.com/javase/tutorial/uiswing/painting/index.html). Also have a look at this article: [Mixing Heavyweight and Lightweight Components](https://www.oracle.com/technical-resources/articles/java/mixing-components.html) – Abra Feb 08 '21 at 08:10

1 Answers1

4

If you look close, you will notice that the 4th set of lines are shifted 2 pixels to the right.

I think you have a 125% UI Scaling going on, so that you have 5 physical pixels for every 4 logical pixels. This is confirmed by the fact that the lines in the posted image are 125 pixels tall, even though the code requested the lines to be 100 pixels long.

This means that when you draw with x + 3 (logically), that actually maps to x + 4 (physically on the monitor). The drawLine() method has correctly moved over 4 pixels instead of 3, and correctly draws a line that is 1 pixel wide.

drawRect() will however separately calculate the left (inclusive) and right (exclusive) sides of the boxes to fill, so for the 3rd set of boxes, the right side is 2 pixels to the right of the left side. It then fills the box that is 2 pixels wide.

Most of us don't have UI Scaling, so we won't see the issue you have.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Oh ok, makes sense, is there a solution to it? So can I draw on the exact pixels, that exist and not the theorectical pixels, that are calculated. It makes even more sense, because if I draw all lines next to each other, there are lines free inbetween. – carlos.gmz Feb 07 '21 at 17:33
  • 1
    @carlos.gmz See [How to disable scaling the UI on Windows, for Java 9 applications?](https://stackoverflow.com/q/47613006/5221149) – Andreas Feb 07 '21 at 17:35