Почему при изменении содержимого в текстовом поле не меняется размер полос прокрутки? - PullRequest
0 голосов
/ 18 апреля 2020

Engli sh не мой родной язык, извините, если есть грамматические ошибки. Это программа для текстового редактора.

Класс Rule используется в качестве заголовка строки для ScrollableTextArea. ScrollableTextArea расширяет JTextArea и реализует Scrollable, он также реализуетMouseMotionListener, так что пользователь может прокручивать (перемещать ручку), нажимая на дорожку.

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.GridLayout;
    import java.awt.Rectangle;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionListener;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import javax.swing.BorderFactory;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.Scrollable;
    import javax.swing.SwingConstants;

    /**
     *Classes required
     *Rule.java
     *ScrollableTextArea
     * @author Dev Parzival
     */
    public class Note extends JPanel{

        static int NUMBER_PANEL_WIDTH=50;
        private ScrollableTextArea scrollableTextArea;
        private Rule rowView;
        private JScrollPane scroll;

        public Note(Dimension size,File file) {

            rowView=new Rule(SwingConstants.VERTICAL,getIncrement());

            scrollableTextArea=new ScrollableTextArea(rowView.getIncrement());

            boolean flag=fetchData(scrollableTextArea, file);
            rowView.setPreferredHeight(scrollableTextArea.getHeight());
            if(!flag)
                return;
            scroll=new JScrollPane(scrollableTextArea);
            scroll.setPreferredSize(size);
            scroll.setRowHeaderView(rowView);
            scroll.setViewportBorder(BorderFactory.createLineBorder(Color.black));

            add(scroll);
            setSize(size);
            setVisible(true);
        }
        private boolean fetchData(JTextArea text,File file){
            FileReader scan;
            BufferedReader br;
            try{
                scan=new FileReader(file);
                String msg="";
                br=new BufferedReader(scan);
                try{

                    while(true){
                        String data=br.readLine();
                        if(data==null)
                            break;
                        msg+=data+"\n";
                    }

                    text.setText(msg);
                }
                catch(IOException ex){
                    JOptionPane.showMessageDialog(this,"Error Occured while reading "+file.getAbsolutePath()+".","Error",JOptionPane.INFORMATION_MESSAGE);
                }
            }
            catch(FileNotFoundException ex){
                JOptionPane.showMessageDialog(this,"Cannot found this path : "+file.getAbsoluteFile(),"Error",JOptionPane.INFORMATION_MESSAGE);
                return false;
            }
            return true;
        }
        /*Here the unit is the height of the text inside the textArea*/
        public int getIncrement(){
            JTextArea ta=new JTextArea();
            return ta.getFontMetrics(ta.getFont()).getHeight();
        }
        public static void createAndShowGUI(){
            JFrame frame = new JFrame("ScrollDemo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(500, 500);
            //Create and set up the content pane.
            JComponent newContentPane = new Note(frame.getSize(),new File("C:\\Users\\DevParzival\\Documents\\pro.txt"));
            newContentPane.setOpaque(true); //content panes must be opaque
            frame.setContentPane(newContentPane);

            //Display the window.
            //frame.pack();
            frame.setVisible(true);
        }
        public static void main(String $[]){
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    }

    class Rule extends JComponent {
        public static int INCH;
        public static final int HORIZONTAL = 0;
        public static final int VERTICAL = 1;
        public static final int SIZE = 35;

        public int orientation;
        private int increment;
        private int units;

        public Rule(int o,int height) {
            orientation = o;
            INCH=height;
            setIncrementAndUnits();
        }


        private void setIncrementAndUnits() {
            increment = units=INCH;
        }

        public int getIncrement() {
            return increment;
        }

        public void setPreferredHeight(int ph) {
            setPreferredSize(new Dimension(SIZE, ph));
        }

        public void setPreferredWidth(int pw) {
            setPreferredSize(new Dimension(pw, SIZE));
        }

        protected void paintComponent(Graphics g) {
            Rectangle drawHere = g.getClipBounds();

            System.out.println(drawHere);

            // Fill clipping area with dirty brown/orange.
            g.setColor(new Color(230, 163, 4));
            g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);

            // Do the ruler labels in a small font that's black.
            g.setFont(new Font("SansSerif", Font.PLAIN, 10));
            g.setColor(Color.black);

            // Some vars we need.
            int end = 0;
            int start = 0;
            int tickLength = 0;
            String text = null;

            // Use clipping bounds to calculate first and last tick locations.
            if (orientation == HORIZONTAL) {
                start = (drawHere.x / increment) * increment;
                end = (((drawHere.x + drawHere.width) / increment) + 1)
                      * increment;
            } else {
                start = (drawHere.y / increment) * increment;
                end = (((drawHere.y + drawHere.height) / increment) + 1)
                      * increment;
            }

            // Make a special case of 0 to display the number
            // within the rule and draw a units label.
    //        if (start == 0) {
    //            text = Integer.toString(0);
    //            tickLength = 10;
    //            if (orientation == HORIZONTAL) {
    //                g.drawLine(0, SIZE-1, 0, SIZE-tickLength-1);
    //                g.drawString(text, 2, 21);
    //            } else {
    //                g.drawLine(SIZE-1, 0, SIZE-tickLength-1, 0);
    //                g.drawString(text, 9, 10);
    //            }
    //            text = null;
    //            start = increment;
    //        }

            // ticks and labels
            for (int i = start; i < end; i += increment) {
                if (i % units == 0)  {
                    tickLength = 10;
                    text = Integer.toString(i/units);
                } else {
                    tickLength = 7;
                    text = null;
                }

                if (tickLength != 0) {
                    if (orientation == HORIZONTAL) {
                        g.drawLine(i, SIZE-1, i, SIZE-tickLength-1);
                        if (text != null)
                            g.drawString(text, i-3, 21);
                    } else {
                        g.drawLine(SIZE-1, i, SIZE-tickLength-1, i);
                        if (text != null)
                            g.drawString(text, 9, i+3+increment/2);
                    }
                }
            }
        }
    }

    class ScrollableTextArea extends JTextArea implements Scrollable,MouseMotionListener {
        private int maxUnitIncrement = 1;

        public ScrollableTextArea(int m) {

            maxUnitIncrement = m;

            //Let the user scroll by dragging to outside the window.
            setAutoscrolls(true); //enable synthetic drag events
            addMouseMotionListener(this); //handle mouse drags
        }

        //Methods required by the MouseMotionListener interface:
        public void mouseMoved(MouseEvent e) { }
        public void mouseDragged(MouseEvent e) {
            //The user is dragging us, so scroll!
            Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
            scrollRectToVisible(r);
        }

        public Dimension getPreferredSize() {
            return new Dimension(500,500);
        }

        public Dimension getPreferredScrollableViewportSize() {
            return getPreferredSize();
        }

        public int getScrollableUnitIncrement(Rectangle visibleRect,
                                              int orientation,
                                              int direction) {
            //Get the current position.
            int currentPosition = 0;
            if (orientation == SwingConstants.HORIZONTAL) {
                currentPosition = visibleRect.x;
            } else {
                currentPosition = visibleRect.y;
            }

            //Return the number of pixels between currentPosition
            //and the nearest tick mark in the indicated direction.
            if (direction < 0) {
                int newPosition = currentPosition -
                                 (currentPosition / maxUnitIncrement)
                                  * maxUnitIncrement;
                return (newPosition == 0) ? maxUnitIncrement : newPosition;
            } else {
                return ((currentPosition / maxUnitIncrement) + 1)
                       * maxUnitIncrement
                       - currentPosition;
            }
        }

        public int getScrollableBlockIncrement(Rectangle visibleRect,
                                               int orientation,
                                               int direction) {
            if (orientation == SwingConstants.HORIZONTAL) {
                return visibleRect.width - maxUnitIncrement;
            } else {
                return visibleRect.height - maxUnitIncrement;
            }
        }

        public boolean getScrollableTracksViewportWidth() {
            return false;
        }

        public boolean getScrollableTracksViewportHeight() {
            return false;
        }

        public void setMaxUnitIncrement(int pixels) {
            maxUnitIncrement = pixels;
        }
    }

Above Pic

Из приведенного выше pi c видно, что изменение содержимого textArea не приводит к изменению размера полос прокрутки. Как можно настроить полосу прокрутки при изменении содержимого внутри scrollableTextArea? Как исправить ошибку?

Заранее спасибо.

...