Полоса прокрутки исчезает при нажатии и изменении размера

Полоса прокрутки исчезает при нажатии и при изменении размера -> старый экран остается, а часть нового экрана появляется местами. Полоса прокрутки исчезает при нажатии, а при изменении размера окна центральная панель искажается (сохраняются старые устаревшие полосы прокрутки и путается текст)

Я создаю маленькую текстовую приключенческую игру старой школы для одного из моих классов. Я новичок в использовании качели, и у меня проблемы с центральной панелью рамы. Единственная часть моего кода, с которой у меня возникают проблемы, — это полоса прокрутки (см. конструктор updateScreen() и GraphicView()). Извините, если за кодом сложно следить, потому что это всего лишь один из многих классов, и есть комментарии к вещам, которые я пробовал ранее, которые имеют те же проблемы.

Если вы хотите запустить его, посмотрите упрощенный код внизу

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

public class GraphicView extends View {

    public static void main(String[] args)
    {
        GraphicView view = new GraphicView();
    }
    GraphicView()
    {
        frame = new JFrame();
        frame.addWindowListener(new GuiWindowListener());
        frame.setLocation(100, 200);
        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        frame.setTitle("Nittany Cubs Gaming GUI");
        frame.setLayout(new BorderLayout());


        //JScrollPain mainPanel = new Panel();
    //  mainPanel = new JPanel();
    //  mainPanel.setLayout(new BorderLayout());

        //northButton = new JButton("Go North");
        //northButton.addActionListener(new NorthButtonActionListener());
        //eastButton = new JButton("Go east");
        //eastButton.addActionListener(new EastButtonActionListener());
        //southButton = new JButton("Go south");
        //southButton.addActionListener(new SouthButtonActionListener());
        //westButton = new JButton("Go west");
        //westButton.addActionListener(new WestButtonActionListener());
        //frame.add(westButton,BorderLayout.WEST);
        //frame.add(southButton,BorderLayout.SOUTH);
        //frame.add(eastButton,BorderLayout.EAST);
        //frame.add(northButton,BorderLayout.NORTH);


//      Panel southPanel = new Panel();
//      mainPanel.add(southPanel, BorderLayout.SOUTH);

    //  Panel northPanel = new Panel();
    //  northPanel.setSize(frame.getWidth(), 50);
    //  northPanel.setBackground(Color.BLACK);
        // add north button to north panel
    //  Button northButton = new Button("North Button");
    //  northButton.setSize(northPanel.getWidth()-10, northPanel.getHeight()-10);
        //northButton.setSize(northPanel.getSize());
        //northButton.setBounds(new Rectangle(northPanel.getBounds()));
        //northButton.setMaximumSize(northPanel.getSize());
    //  northButton.setBackground(Color.PINK);
    //  northButton.addActionListener(new NorthButtonActionListener());
    //  northPanel.add(northButton);
        // add north panel to main panel
    //  mainPanel.add(northPanel, BorderLayout.NORTH);

        northButton = new JButton("Go North");
        northButton.addActionListener(new NorthButtonActionListener());
        frame.add(northButton, BorderLayout.NORTH);

        eastButton = new JButton("Go east");
        eastButton.addActionListener(new EastButtonActionListener());
        frame.add(eastButton, BorderLayout.EAST);

        southButton = new JButton("Go south");
        southButton.addActionListener(new SouthButtonActionListener());
        frame.add(southButton, BorderLayout.SOUTH);

        westButton = new JButton("Go west");
        westButton.addActionListener(new WestButtonActionListener());
        frame.add(westButton, BorderLayout.WEST);

        text = "";
        mainPanel = new JPanel();
        textArea = new JTextArea(text);
        textArea.setEditable(false);
        //mainPanel.add(textArea);
        //scroller = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        scroller = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        frame.add(scroller,BorderLayout.CENTER);

        updateScreen();
    }

    private static void updateScreen()
    {
    //  JTextArea ta = new JTextArea(text);
        textArea = new JTextArea(text);
        //mainPanel.add(textArea);
        scroller = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        //scroller = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        frame.add(scroller,BorderLayout.CENTER);
        frame.setVisible(true);

    //  JScrollPane scroller = new JScrollPane(ta);
      // disables editing
     //   ta.setEditable(false);
    //  scroller = new JScrollPane(ta, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    //  scroller.setBounds(3, 3, 300, 200);

    //  label = new JLabel("<html>" + text + "</html>");

    //  label.setLayout(new BorderLayout());

    //  label.setVerticalAlignment(SwingConstants.TOP);
    //  scroller = new JScrollPane(label, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        //scroller.addMouseWheelListener(new MyMouseWheelListener());
//      scroller.createVerticalScrollBar();
//      scroller.createHorizontalScrollBar();
//      scroller.setAutoscrolls(true);


//      mainPanel.add(scroller, BorderLayout.CENTER);
//      frame.getContentPane().add(mainPanel);
//      frame.add(scroller,BorderLayout.CENTER);
//      frame.setVisible(true);
    }

    @Override
    public void informInvalidGoDirection(String direction) {
        text += "\nYou hit your nose on the wall trying to go " + direction + ". ";
        updateScreen();
    }

    @Override
    public void informPlayerMoved() {
        // TODO Auto-generated method stub

    }

    @Override
    public void look() {
        // TODO Auto-generated method stub
        Location currentLocation = Application.instance().playerCurrentLocation();
        text += currentLocation.description()  + " " + getItemsDescription(currentLocation) + " " +
                             getMobsDescription(currentLocation) + " " +
                             getCanMoveDirectionsDescription(currentLocation);
        updateScreen();
    }

    private class NorthButtonActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent ev)
        {
            Location currentLocation = Application.instance().playerCurrentLocation();
            boolean isLocationValid = Application.instance().isThereALocationNorthOf(currentLocation);
            if(isLocationValid)
            {

                Application.instance().movePlayerNorth();

                Location newLocation = Application.instance().playerCurrentLocation();
                text = newLocation.description() +
                         getItemsDescription(newLocation) +
                         getMobsDescription(newLocation) +
                         getCanMoveDirectionsDescription(newLocation);
                updateScreen();
            }
            else
            {
                informInvalidGoDirection("north");
            }
        }
    }

    private class SouthButtonActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent ev)
        {
            Location currentLocation = Application.instance().playerCurrentLocation();
            boolean isLocationValid = Application.instance().isThereALocationSouthOf(currentLocation);
            if(isLocationValid)
            {
                Application.instance().movePlayerSouth();

                Location newLocation = Application.instance().playerCurrentLocation();
                text = newLocation.description() +
                         getItemsDescription(newLocation) +
                         getMobsDescription(newLocation) +
                         getCanMoveDirectionsDescription(newLocation);
                updateScreen();
            }
            else
            {
                informInvalidGoDirection("south");
            }
        }
    }

    private class EastButtonActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent ev)
        {
            Location currentLocation = Application.instance().playerCurrentLocation();
            boolean isLocationValid = Application.instance().isThereALocationEastOf(currentLocation);
            if(isLocationValid)
            {
                Application.instance().movePlayerEast();

                Location newLocation = Application.instance().playerCurrentLocation();
                text = newLocation.description() +
                         getItemsDescription(newLocation) +
                         getMobsDescription(newLocation) +
                         getCanMoveDirectionsDescription(newLocation);
                updateScreen();
            }
            else
            {
                informInvalidGoDirection("east");
            }
        }
    }

    private class WestButtonActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent ev)
        {
            Location currentLocation = Application.instance().playerCurrentLocation();
            boolean isLocationValid = Application.instance().isThereALocationWestOf(currentLocation);
            if(isLocationValid)
            {
                Application.instance().movePlayerWest();                

                Location newLocation = Application.instance().playerCurrentLocation();
                text = newLocation.description() +
                         getItemsDescription(newLocation) +
                         getMobsDescription(newLocation) +
                         getCanMoveDirectionsDescription(newLocation);
                updateScreen();
            }
            else
            {
                informInvalidGoDirection("west");
            }
        }
    }


    private static class GuiWindowListener extends WindowAdapter
    {
        @Override
        public void windowClosing(WindowEvent ev)
        {
            ev.getComponent().setVisible(false);
            System.exit(0);
        } /* end windowClosing */
    } /* end GuiWindowListener */



    private static final int FRAME_HEIGHT = 480;
    private static final int FRAME_WIDTH = 640;
    private static JButton northButton;
    private static JButton southButton;
    private static JButton eastButton;
    private static JButton westButton;
//  private static JLabel label;
    private static String text;
    private static JPanel mainPanel;
    private static JScrollPane scroller;
    private static JFrame frame;
    private static JTextArea textArea;

}

Вот упрощенная версия, чтобы подчеркнуть проблему, с которой я столкнулся ПРИМЕЧАНИЕ -> проблема с прокруткой возникает до тех пор, пока в следующий раз не произойдет screenUpdate()

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class GraphicViewSimplified {
    public static void main(String[] args)
    {
        GraphicViewSimplified view = new GraphicViewSimplified();
    }
    GraphicViewSimplified()
    {
        frame = new JFrame();
        frame.addWindowListener(new GuiWindowListener());
        frame.setLocation(100, 200);
        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        frame.setTitle("Nittany Cubs Gaming GUI");
        frame.setLayout(new BorderLayout());

        northButton = new JButton("Go North");
    //  northButton.addActionListener(new NorthButtonActionListener());
        frame.add(northButton, BorderLayout.NORTH);

        eastButton = new JButton("Go east");
    //  eastButton.addActionListener(new EastButtonActionListener());
        frame.add(eastButton, BorderLayout.EAST);

        southButton = new JButton("Go south");
    //  southButton.addActionListener(new SouthButtonActionListener());
        frame.add(southButton, BorderLayout.SOUTH);

        westButton = new JButton("Go west");
    //  westButton.addActionListener(new WestButtonActionListener());
        frame.add(westButton, BorderLayout.WEST);

        text = ";lakjd;lfkjasd;lfkjas;ldfkjas;lkdfj;a\naj;lsdkfjas;lkdjf\naal;skjfw;lk\n";
        //mainPanel = new JPanel();
        textArea = new JTextArea(text);
        textArea.setEditable(false);
        scroller = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        frame.add(scroller,BorderLayout.CENTER);

        while(true)
        {
            updateScreen();
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private static void updateScreen()
    {
        String alph = "abcdefghijklmnopqrstuvwxyz";

        int firstInt = (int)(Math.random()*100);
        int secondInt = (int)(Math.random()*100);

        for(int i = 0; i < firstInt ; i++)
        {

            text += alph.charAt((int)(Math.random()*alph.length()));
        }

        text += "\n";


        for(int i = 0; i < secondInt ; i++)
        {       
            text += alph.charAt((int)(Math.random()*alph.length()));
        }

        text += "\n";

    //  JTextArea ta = new JTextArea(text);
        textArea = new JTextArea(text);
        textArea.setEditable(false);
        //mainPanel.add(textArea);
        scroller = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        //scroller = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        frame.add(scroller,BorderLayout.CENTER);
        frame.setVisible(true);

    }

    private static class GuiWindowListener extends WindowAdapter
    {
        @Override
        public void windowClosing(WindowEvent ev)
        {
            ev.getComponent().setVisible(false);
            System.exit(0);
        } /* end windowClosing */
    } /* end GuiWindowListener */

    private static final int FRAME_HEIGHT = 480;
    private static final int FRAME_WIDTH = 640;
    private static JButton northButton;
    private static JButton southButton;
    private static JButton eastButton;
    private static JButton westButton;
    private static String text;
//  private static JPanel mainPanel;
    private static JScrollPane scroller;
    private static JFrame frame;
    private static JTextArea textArea;
}

person JLaudio    schedule 01.12.2013    source источник
comment
Не спите на EDT; делать см. Параллелизм в Swing.   -  person trashgod    schedule 01.12.2013


Ответы (2)


Сначала вы блокируете EDT здесь, это неправильно:

while (true) {
    updateScreen();
    try {
        Thread.sleep(1500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Для этой цели вы можете использовать Swing Timer, его можно использовать для обновления по интервалу, также 1500 может быть большим интервалом, потому что вы получаете лаги при изменении размера кадра.

Timer t = new Timer(1000, new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent arg0) {
         updateScreen();
    }
});
t.start();

Как по мне, вам действительно нужно SwingWorker. Вот хороший пример этого.

Прочтите о параллелизме в Swing, Swing Timer и SwingWorker.

person alex2410    schedule 01.12.2013
comment
ну, в моей реальной работе я не использую таймер ни для чего, это было просто для рабочего примера проблемы, с которой я столкнулся, чтобы вы, ребята, увидели, о чем я говорю. Экран обновляется и должен обновляться только при нажатии кнопки и изменении отображаемого текста. Прокрутка должна по-прежнему работать, даже если она не в цикле, как в графическом интерфейсе С++, верно? - person JLaudio; 02.12.2013

Хорошо, я понял ответ на свой вопрос, который мне нужно было добавить для удаления (OldComponents) revalidate(), затем добавить (newComponent), затем revalidate() в функцию updateScreen(). У меня это работает! Хотя спасибо за помощь

person JLaudio    schedule 03.12.2013