问题描述:

For some reason my scrollbar is appearing but it is not working. What is suppose to happen is using the scrollbar to scroll through the text of the textarea. Can somebody please explain why this isnt working?

import java.io.*;

import java.awt.event.*;

import java.awt.*;

import javax.swing.*;

public class App extends JFrame{

private JPanel paneel;

public App(){

paneel = new AppPaneel();

setContentPane(paneel);

}

public static void main(String args[]){

JFrame frame = new App();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setSize(400, 400);

frame.setTitle("Auto Clicker");

frame.setVisible(true);

}

}

class AppPaneel extends JPanel{

private JTextField delayField, xLocation, yLocation;

private JTextArea listArea;

private JButton addButton, saveButton, runButton;

private JScrollPane scroll;

public AppPaneel(){

setLayout(null);

delayField = new JTextField();

delayField.setBounds(10, 10, 85, 25);

delayField.setText("delay in ms");

xLocation = new JTextField();

xLocation.setBounds(105, 10, 85, 25);

xLocation.setText("X position");

yLocation = new JTextField();

yLocation.setBounds(200, 10, 85, 25);

yLocation.setText("Y position");

addButton = new JButton("Add");

addButton.setBounds(295, 10, 75, 24);

addButton.addActionListener(new AddHandler());

listArea = new JTextArea();

listArea.setBounds(10, 45, 360, 180);

scroll = new JScrollPane(listArea);

scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

scroll.setBounds(370, 45, 20, 180);

saveButton = new JButton("Save");

saveButton.setBounds(10, 230, 85, 24);

runButton = new JButton("Run (F1)");

runButton.setBounds(105, 230, 85, 24);

runButton.addActionListener(new RunHandler());

add(delayField);

add(xLocation);

add(yLocation);

add(addButton);

add(listArea);

add(saveButton);

add(runButton);

add(scroll);

}

class AddHandler implements ActionListener{

public void actionPerformed(ActionEvent a){

listArea.setText(listArea.getText() + delayField.getText() + ", " + xLocation.getText() + ", " + yLocation.getText() + ", " + "click;" + "\n");

}

}

class RunHandler implements ActionListener{

private Robot bot;

private String text;

int foo = Integer.parseInt("1234");

public void actionPerformed(ActionEvent b) {

try{

text = listArea.getText();

bot = new Robot();

for(String line : text.split("\\n")){

int delay = Integer.parseInt((line.substring(0, 4)));

int xpos = Integer.parseInt((line.substring(6, 10)));

int ypos = Integer.parseInt((line.substring(12, 16)));

bot.mouseMove(xpos, ypos);

Thread.sleep(delay);

bot.mousePress(InputEvent.BUTTON1_MASK);

bot.mouseRelease(InputEvent.BUTTON1_MASK);

}

}

catch (AWTException | InterruptedException e){

e.printStackTrace();

}

}

}

}

网友答案:

Don't use null layouts and setBounds as it is messing up your program. We tell folks time and time again not to do this for a reason -- by setting the JTextArea's bound you constrain its size so it won't grow when it needs to. The solution, as always -- learn and use the layout managers. Set the JTextArea's column and row properties but not its bounds, its size, or its preferred size.

Next don't do this: Thread.sleep(delay); in your Swing application as it will put the entire application to sleep. Use a Swing Timer instead for any delays. The tutorials can help you use this.

For a non-functional layout example:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;

@SuppressWarnings("serial")
public class App2 extends JPanel {
    private static final int GAP = 5;
    private JTextField textField1 = new JTextField(GAP);
    private JTextField textField2 = new JTextField(GAP);
    private JTextField textField3 = new JTextField(GAP);
    private JTextArea textArea = new JTextArea(15, 30);

    public App2() {
        JPanel topPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
        topPanel.add(textField1);
        topPanel.add(textField2);
        topPanel.add(textField3);
        topPanel.add(new JButton("Add"));

        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        JPanel bottomPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
        bottomPanel.add(new JButton("Save"));
        bottomPanel.add(new JButton("Run (F1)"));
        bottomPanel.add(new JLabel(""));
        bottomPanel.add(new JLabel(""));

        setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        setLayout(new BorderLayout(GAP, GAP));
        add(topPanel, BorderLayout.PAGE_START);
        add(scrollPane, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Auto Clicker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new App2());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

Your whole approach is wrong. You should not be using a null layout. For example:

scroll.setBounds(370, 45, 20, 180);

you are setting the width to 20. Well how to you expect the text area to display in 20 pixels? This is the problem with using setBounds(...), the random numbers you use have no meaning. Let a layout manager do its job. Also:

add(listArea);

The problem is that a component can only have a single parent. You originally created the JScrollPane with the text area which is correct.

But then you add the text area directly to the frame which removes it from the scroll pane so the scroll panel will no longer function.

Get rid of that statement and just add the scroll pane to the frame.

However, I don't recommend you use this as your final solution. I just wanted to mention the current problems so you hopefully understand the benefits of using layout managers and so that you don't try to share components again.

The proper solution is to use layout managers as has been suggested by the "Community Wiki". Then the layout manager will determine the size and location of each component so you don't need to worry about calculating your pixel values correctly.

相关阅读:
Top