How do I change the size of a rectangle while pain

2019-08-30 12:48发布

问题:

Actually I am new to java gui, and here I want to change the rectangle height whenever we put something in text field and press button, but I don't know how to do it, actually I checked in a ton of sited but I couldn't find an easy way.Actually I can't find how to change rectangle size that is inside paintComponent inside the MyPanel class.

(The logic for height change is how many vowels capital and small,and consonents and other things are there in string)

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Hist{
    int h1=0,h2=0,h3=0,h4=0,h5=0;
    JFrame f=new JFrame();
    JButton b=new JButton("click");
    JTextField text=new JTextField(30);


public static void main(String args[]){
    Hist h=new Hist();

}

Hist(){

    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLayout(new FlowLayout());
    f.add(new MyPanel(h1,h2,h3,h4,h5));
    f.setSize(400,300);
    f.setVisible(true);

    f.add(b);
    f.add(text);

    thehandler handler=new thehandler();
    b.addActionListener(handler);

}
class thehandler implements ActionListener{
    public void actionPerformed(ActionEvent event){
        if(event.getSource()==b){
            h1=0;h2=0;h3=0;h4=0;h5=0;
            String s;
            s=text.getText();
            char[] ar=s.toCharArray();
            for(int i=0;i<s.length();i++){
                if(ar[i]=='a'||ar[i]=='e'||ar[i]=='i'||ar[i]=='o'||ar[i]=='u'){
                    h1=h1+10;
                }
                else if(ar[i]=='A'||ar[i]=='E'||ar[i]=='I'||ar[i]=='O'||ar[i]=='U'){
                    h2=h2+10;
                }
                else{
                    h5=h5+10;
                }
            }

        }
    }

 }
}


class MyPanel extends JPanel{
    int x1,x2,x3,x4,x5;
    public MyPanel(int a,int b,int c,int d,int e){
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
        x1=a;x2=b;x3=c;x4=d;x5=e;
    }
    public Dimension getPreferredSize(){
        return new Dimension(350,200);
    }
    public void paintComponent(Graphics g){
        super.paintComponents(g);
        g.setColor(Color.red);
        g.fillRect(25, 25, 30,x1);

        g.setColor(Color.red);
        g.fillRect(75, 25, 30, x2);

        g.setColor(Color.red);
        g.fillRect(125, 25, 30,x3);

        g.setColor(Color.red);
        g.fillRect(175, 25, 30, x4);

        g.setColor(Color.red);
        g.fillRect(225, 25, 30, x5);

    }
}

回答1:

"Actually I can't find how to change rectangle size that is inside paintComponent"

It looks like the way you're doing it will only change the height and not the y location. Which would be fine if it were an upside down histogram.

What you need to do is have a starting point for y, say 400 for a screen with height 450, so the horizon is near the bottom

int y = 400;

So when you draw it will be

g.fillRect(25, y - height, 30, height)

Now height will be the y starting point, 400. And when you want to increase it, you actually need to decrease 400.

So if you want the height to be 150, then you need to -150

g.fillRect(25, y - 150, 30, height);

This will give the effect a bar rising from the horizon line

For every g.fillRect you should calculate a new height, so you can have a height varaible. and a final INCREMENT variable based on how many vowels. So something like this

final int INCREMENT = 25;
int height;

....

height = numberOfAs * INCREMENT;
g.fillRect(25, y - height, 30, height);
height = numberOfEs * INCREMENT;
g.fillRect(75, y - height, 30, height);
height = numberOfOs * INCREMENT;
g.fillRect(125, y - height, 30, height);
height = numberOfIs * INCREMENT;
g.fillRect(175, y - height, 30, height);
height = numberOfUs * INCREMENT;
g.fillRect(225, y - height, 30, height);

Run this example to see what I'm talking about

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Histogram extends JPanel {

    private static final int DIM_WIDTH = 300;
    private static final int DIM_HEIGHT = 450;

    int height;
    private static final int INCREMENT = 50;
    int numberOfAs = 4;
    int numberOfEs = 2;
    int numberOfIs = 1;
    int numberOfOs = 5;
    int numberOfUs = 6;
    int y = 400;

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        height = numberOfAs * INCREMENT;
        g.fillRect(25, y - height, 30, height);
        height = numberOfEs * INCREMENT;
        g.fillRect(75, y - height, 30, height);
        height = numberOfOs * INCREMENT;
        g.fillRect(125, y - height, 30, height);
        height = numberOfIs * INCREMENT;
        g.fillRect(175, y - height, 30, height);
        height = numberOfUs * INCREMENT;
        g.fillRect(225, y - height, 30, height);
    }

    public static void createAndShowGui() {
        JFrame frame = new JFrame();
        frame.add(new Histogram());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);

    }

    public Dimension getPreferredSize() {
        return new Dimension(DIM_WIDTH, DIM_HEIGHT);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

From left to right with an INCREMENT of 50 pixels per letter

As = 4;
Es = 2;
Os = 5;
Is = 1;
Us = 6;

Also in a program where you want to be able to control the the repaint with a text field entry, you can have setters in your MyPanel class that will set the values of the numberOfXs variables. After you get them from whatever method you use to get them, just call setNumberOfAs(int numberOfAs) and the rest of the setters, and call repaint. So for each time an input is taken from the textField, and you have updated the variabels in MyPanel, the painted histogram should update.


UPDATE

Another way you can do it is to make both the ActionListener and the MyPanel inner classes of Hist. That way can they can share the global variables of Hist. Make the NumberOfXs variable members of the Hist class so all inner classes can share. In the ActionListener class in your actionPerformed, change the variables accordingly and repaint the MyPanel. If you did it this way, you wouldn't need to pass an parameters to the constructor of MyPanel


UPDATE 2

I don't want to do your complete assignment for you, so I'll give you a basic outline.

  • Make both class inner classes of Hist
  • Have the numberOfXs variables class members of Hist, not in MyPanel
  • Create an instance of MyPanel in Hist as a class member so it can be accesed by the ActionListener
  • Get the values for the numberOfXs in your actionPerformed then call repaint

Something like this

public class Hist {
    MyPanel myPanel = new MyPanel();
    int numberOfAs;
    int numberOfEs;
    int numberOfIs;
    int numberOfOs;
    int numberOfUs;

    private class MyPanel extends JPanel {
        // do your painting
    }

    private class MyListener implements ActionListener {
        public void actionPerformed(ActionEvent e){
            // get the values for numberOfXs however you do it. Make sure to numberOfXs = someValue
            myPanel.repaint();
        }
    }
}


回答2:

In your MyPanel define a method(s) to pass values and set them to the x1 - x5 fields.

e.g.

public void setValues(int a,int b,int c,int d,int e){
    x1=a;x2=b;x3=c;x4=d;x5=e;
}

When something chnages just call the setValues() with proper calculated values.