Fensterinhalt seitenweise scrollen

Ich stelle ich einem Fenster (eigenen) HTML-Code dar. Der Anzeigebereich (eine JEditorPane falls das wichtig ist) liegt in einer JScrollPane (im Code unten scroll genannt).

Das ganze befindet sich in einem JFrame (von den ich ausnahmsweise tatsächlich abgeleitte habe, um createRootPane zu überschreiben):

     * Diese Methode aus JFrame wird überschrieben, um den Tastendrücke
     * abfangen und behandeln zu können.
     */
    @Override
    protected JRootPane createRootPane() {
        Action escapeActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                dispose();
            }
        };
        Action homeActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                int minimum = scroll.getVerticalScrollBar().getMinimum();
                scroll.getVerticalScrollBar().setValue(minimum);
            }
        };
        Action endActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                int maximum = scroll.getVerticalScrollBar().getMaximum();
                scroll.getVerticalScrollBar().setValue(maximum);
            }
        };
        Action pageUpActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                //JViewport viewPort = scroll.getViewport();
                //viewPort.
                System.out.println("Page up");
            }
        };
        Action pageDownActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                //JViewport viewPort = scroll.getViewport();
                //viewPort.
                System.out.println("Page down");
            }
        };

        JRootPane rootPane = new JRootPane();
        InputMap inputMap = rootPane.getInputMap(
                JComponent.WHEN_IN_FOCUSED_WINDOW);
        KeyStroke homeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0);
        inputMap.put(homeStroke, "HOME");
        KeyStroke endStroke = KeyStroke.getKeyStroke(KeyEvent.VK_END, 0);
        inputMap.put(endStroke, "END");
        KeyStroke pageUpStroke = KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0);
        inputMap.put(pageUpStroke, "PAGE_UP");
        KeyStroke pageDownStroke = KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0);
        inputMap.put(pageDownStroke, "PAGE_DOWN");
        KeyStroke escapeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
        inputMap.put(escapeStroke, "ESCAPE");

        rootPane.getActionMap().put("ESCAPE", escapeActionListener);
        rootPane.getActionMap().put("HOME", homeActionListener);
        rootPane.getActionMap().put("END", endActionListener);
        rootPane.getActionMap().put("PAGE_UP", pageUpActionListener);
        rootPane.getActionMap().put("PAGE_DOWN", pageDownActionListener);

        return rootPane;
    }

Home (Pos1) und End funktionieren, wie sie sollen, die Frage ist, was ich bei Page Down und Page Up eintrage. Ich hab schon gegoogelt und für Tabellen auch Lösungen gefunden, aber nichts, das ich einfach so übertragen konnte. Hat hier vielleicht jemand eine weitere Suchanregung oder gar Lösung?

Mir leuchtet nicht ein, warum Du die Methode überschreiben willst/musst.

Was soll denn bei den beiden Aktionen passieren? Soll da ähnlich wie beim Browser (mittels Leertaste) zum nächsten nicht sichtbaren Abschnitt/Bereich hoch und runter geskrollt werden? Diesen könntest Du ja mittels getVisibleRect an der EditorPane berechnen und scrollRectToVisible setzen.

Danke für die schnelle Antwort.

[QUOTE=_Michael;28279]Mir leuchtet nicht ein, warum Du die Methode überschreiben willst/musst.
[/QUOTE]

Der Inhalt der Methode ist ja oben zu sehen: Um Tastatureingaben einzufangen und zu behandeln. Deine Nachfrage impliziert, das das auch anders geht, ohne diese Methode zu überschreiben.

Diese Methoden sind mir durchaus auch begegnet. Mir ist nur unklar, wie getVisibleRect mit scroll.getVerticalScrollBar().getMaximum() bzw. geMinimum() zusammenhängt. Ich werde mal experimentieren, ob das irgendwie zusammen passt.

Ja, man könnte sich auch einfach RootPane, ContentPane oder sonstiges per Methode „holen“ und so deren Input- und ActionMap bearbeiten. Oder einfach die Maps von JScrollPane, JEditorPane nutzen, letztendlicht muss die Komponenten ja nur im sichtbaren Fenster verbaut sein (Du verwendest ja JComponent.WHEN_IN_FOCUSED_WINDOW)

Eigentlich gar nicht. Aber wenn man die Koordinaten des Ausschnitts kennt der angezeigt wird, kann man ja leicht die der „benachbarten“ Abschnitte ausrechnen.

Falls noch jemand dieses Problem hat oder per Google hier landet, ich habe mit

        int minimum = scroll.getVerticalScrollBar().getMinimum();
        int actualPos = scroll.getVerticalScrollBar().getValue();
        int maximum = scroll.getVerticalScrollBar().getMaximum();

        Rectangle rect = scroll.getVisibleRect();
        System.out.println("Position:
"
                + "	Minimum    : " + minimum     + "
"
                + "	aktuell    : " + actualPos   + "
"
                + "	Maximum    : " + maximum     + "
"
                + "	Rect x     : " + rect.x      + "
"
                + "	Rect y     : " + rect.y      + "
"
                + "	Rect width : " + rect.width  + "
"
                + "	Rect height: " + rect.height + "
");
    }

Testausgaben vorgenommen.

Ganz oben:

Position:
	Minimum    : 0
	aktuell    : 0
	Maximum    : 4137
	Rect x     : 0
	Rect y     : 0
	Rect width : 992
	Rect height: 697

Ganz unten:


Position:
	Minimum    : 0
	aktuell    : 3443
	Maximum    : 4137
	Rect x     : 0
	Rect y     : 0
	Rect width : 992
	Rect height: 697

Leider ist nicht 3443 + 697 = 4137, sondern 4140. Trotzdem habe ich mit der folgenden Lösung ein sich “gut” anfühlendes Scrollverhalten erreicht:

    /**
     * Diese Methode aus JFrame wird überschrieben, um den Tastendrücke
     * abfangen und behandeln zu können.
     */
    @Override
    protected JRootPane createRootPane() {
        Action escapeActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                dispose();
            }
        };
        Action homeActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                int minimum = scroll.getVerticalScrollBar().getMinimum();
                scroll.getVerticalScrollBar().setValue(minimum);
            }
        };
        Action endActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                int maximum = scroll.getVerticalScrollBar().getMaximum();
                scroll.getVerticalScrollBar().setValue(maximum);
            }
        };
        Action pageUpActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                int minimum = scroll.getVerticalScrollBar().getMinimum();
                int actualPos = scroll.getVerticalScrollBar().getValue();
                int height = scroll.getVisibleRect().height;
                actualPos -= height;
                if (actualPos < minimum) {
                    actualPos = minimum;
                }
                scroll.getVerticalScrollBar().setValue(actualPos);
            }
        };
        Action pageDownActionListener = new AbstractAction() {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                int actualPos = scroll.getVerticalScrollBar().getValue();
                int maximum = scroll.getVerticalScrollBar().getMaximum();
                int height = scroll.getVisibleRect().height;
                actualPos += height;
                if (actualPos > maximum) {
                    actualPos = maximum;
                }
                scroll.getVerticalScrollBar().setValue(actualPos);
            }
        };

        JRootPane rootPane = new JRootPane();
        InputMap inputMap = rootPane.getInputMap(
                JComponent.WHEN_IN_FOCUSED_WINDOW);
        KeyStroke homeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0);
        inputMap.put(homeStroke, "HOME");
        KeyStroke endStroke = KeyStroke.getKeyStroke(KeyEvent.VK_END, 0);
        inputMap.put(endStroke, "END");
        KeyStroke pageUpStroke = KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0);
        inputMap.put(pageUpStroke, "PAGE_UP");
        KeyStroke pageDownStroke = KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0);
        inputMap.put(pageDownStroke, "PAGE_DOWN");
        KeyStroke escapeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
        inputMap.put(escapeStroke, "ESCAPE");

        rootPane.getActionMap().put("ESCAPE", escapeActionListener);
        rootPane.getActionMap().put("HOME", homeActionListener);
        rootPane.getActionMap().put("END", endActionListener);
        rootPane.getActionMap().put("PAGE_UP", pageUpActionListener);
        rootPane.getActionMap().put("PAGE_DOWN", pageDownActionListener);

        return rootPane;
    }

Edit: Nachtrag: Ich bin beim Überschreiben der Methode geblieben, weil es sich dabei um ein dialogartiges Fenster handelt, das außer dem Anzeigebereich und der ScrollPane nur noch einen Button zum verlassen hat. Und ich gerne wollte, dass die Tastaturbefehle auch dann funktionieren, wenn der Button zufällig den Focus hat.