Swing Hex-Editor

  • Themenstarter Themenstarter Gast2
  • Beginndatum Beginndatum
G

Gast2

Gast
Hi,
ich bin grad dabei mir einen kleinen Hex editor zu schreiben. Nun wollte ich meine Textarea ein wenig "aufmotzen".
Vorgestellt hatte ich mir das in etwa so:
Links sollte immer eine laufende Zeilenummer stehn, in diese sollte man auch nicht mit dem Cursor hineindürfen. Daneben dann in viererblöcken die Hexzeichen. Evtl. noch ein wenig Highlighting rein.
Mit welcher Komponente kann ich das am besten realisieren, und gibt es irgendwo schöne Tutorials wo man sich mal einlesen könnte?
 
Ok, das hört sich wirklich ein wenig kompliziert an. 😉
Werd mich da morgen abend aber mal einlesen und sicherlich mit der ein oder anderen Frage wieder auftauchen 😀
 
Den Zeilenzähler könnte man mit nem InputMethodListener realisieren, der der nebigen ZeilenanzeigeKomponente sagt, dass sie sich bitte um eins erweitern möge, wenn die Eingabe ein Zeilenumbruch war. Wenn beide dieselben Fonts benutzen...könnte ...es fast klappen.

Viererblöcke können so realisiert werden, dass die JTextArea per Konstruktor auf 4 Spalten begrenzt und setLineWrap(true) gesetzt wird, JTextArea.setMargin(Insets m) könnte interessant werden.
 
Den Zeilenzähler könnte man mit nem InputMethodListener realisieren, der der nebigen ZeilenanzeigeKomponente sagt, dass sie sich bitte um eins erweitern möge, wenn die Eingabe ein Zeilenumbruch war. Wenn beide dieselben Fonts benutzen...könnte ...es fast klappen.
Davon rate ich ab. Das Modell der Zeilennummern-Komponente sollte ausschließlich vom Dokument abhängen.

Ebenius
 
Viererblöcke können so realisiert werden, dass die JTextArea per Konstruktor auf 4 Spalten begrenzt und setLineWrap(true) gesetzt wird, JTextArea.setMargin(Insets m) könnte interessant werden.
Ich habe das versuch so umzusetzen:
Java:
    public static void main(String[] args) {
        JFrame frame = new JFrame();

        JTextArea area = new JTextArea(5, 4);
        area.setLineWrap(true);
        area.setMargin(new Insets(5,5,5,5));

        frame.add(area);
        frame.setVisible(true);
    }
Hat leider nicht funktioniert, habe ich da was falsch verstanden?

EDIT:
Danke für die Suchworte Ebenius, habe mich da grade ein wenig eingelesen und ich denke dass ich damit zurechtkommen sollte.
Für die Zeilen habe ich jetzt die Variante mit dem Rowheader übernommen, das funktioniert auch schonmal prima. Welche Komponente sollte ich da am besten verwenden? Im Moment tendiere ich dazu ne JTextArea zu verwenden (mit dem selben Schriftgrößeneinstellungen der Textpane. Oder gibts da nen eleganteren Weg, dass die Zeilennummern immer auf der selben Höhe sind wie der Text in der Textpane?
Jetzt bleibt eigentlich nur noch die Frage offen wie ich es am besten diese 4er blöcke realisiere 🙂
 
Zuletzt bearbeitet von einem Moderator:
Versteh ich nicht. Wie sonst kann man events, die einen Zeilenumbruch beim editieren kennzeichnen, abfangen? Mit updateUI() oder so?
Listener am Document (welches das Modell hinter Textkomponenten ist).

Oder gibts da nen eleganteren Weg, dass die Zeilennummern immer auf der selben Höhe sind wie der Text in der Textpane?
Das habe ich noch nie für eine JTextPane bzw. JEditorPane gemacht. Ich gehe davon aus, dass die Komponente Dir zu jedem Index im Document eine View und deren Position geben kann. Darüber müsste man dann die Zeilennumerierung machen. Eventuell hat sowas im WWW schonmal jemand für Dich gemacht; keine Ahnung. 🙂

Ich würde dann wahrscheinlich ein JComponent nehmen und auf diesem per CellRendererPane ein JLabel rendern. Setzt aber ein bisschen Wissen über painting in AWT voraus. Noch eine Textkomponente würde ich für den RowHeader nicht benutzen.

Ebenius
 
So, ich denke ich fang dann mal an und programmier schonmal so nen ersten entwurf, der schonmal die ganzen funktionalitäten bereithält. sowas wie 4erblöcke, Zeilennummern und evtl. nen bissl highlighting kann ich ja noch später hinzufügen.
Ich würde mir diesen Hexeditor gerne als eine Art "Komponente" programmieren, so dass ich ihn später bei mir im programm an verschiedenen Stellen einsetzen kann (wie ne JTextarea z.b.).
Ich habe bisher noch keine Komponenten selbst geschrieben, daher ist mir nicht ganz klar wie ich anfangen sollte. Soll mein Hexeditor von JPanel erben, auf dem ich dann alle anderen Komponenten (wären dann 2 TextPane und 2 JLabel) positioniere, oder besser von JComponent?
 
Sorry für den Doppelpost, aber ich habe jetzt noch eine weitere Frage:
In meiner GUI habe ich jetzt 2 TextAreas, sobald sich in einer etwas ändert sollen diese Änderungen auf die zweite übertragen werden.

Java:
    public JavaHexEditorView(SingleFrameApplication app) throws BadLocationException {
        super(app);

        initComponents();

        ((AbstractDocument)hexArea.getDocument()).setDocumentFilter(new HexDocumentFilter());
        
        textArea.getDocument().addDocumentListener(new DocumentListener() {

            public void insertUpdate(DocumentEvent e)
            {
                 /* hier findet eig. noch Umrechnung String->Hex statt */
                  hexArea.setText(textArea.getText());
            }

            public void removeUpdate(DocumentEvent e)
            {}

            public void changedUpdate(DocumentEvent e)
            {}
        });

        hexArea.getDocument().addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent e)
            {
                 /* hier findet eig. noch Umrechnung Hex->String statt */
                 textArea.setText(hexArea.getText());
            }

            public void removeUpdate(DocumentEvent e)
            {}

            public void changedUpdate(DocumentEvent e)
            {}
        });
    }
Diese zwei Listener rufen sich ja natürlich bei Änderungen immer gegenseitig auf, und ich bekomme eine java.lang.IllegalStateException: Attempt to mutate in notification.
Wie löst man sowas normalerweise? Über Key- / MouseListener? Wobei ich da immer die Befürchtung habe, dass dann immernoch daten reinkommen können ohne dass einer der Listener greift (drag&drop oä.).
 
Zuletzt bearbeitet von einem Moderator:
Mach doch in diesem Fall einfach das selbe Document in beide JTextAreas. Dann brauchst Du überhaupt keine Listener; die beiden haben schlicht das selbe Modell.

Um die Komponente zu bauen, würde ich eine Klasse von JComponent ableiten und sie mit allen sinnvollen gettern und settern ausstatten. Von JPanel sollte man nur ableiten, wenn der Sinn der Komponente für den Benutzer der ist, andere Komponenten draufzupacken. Das sollte hier nicht zutreffen.

Denk am besten auch nochmal darüber nach, wie das Modell der Komponente aussehen soll. Da es sich um einen HexEditor handelt, müsste das Modell eigentlich bytes verarbeiten, bytes einfügen und löschen können, Zuhörer über Änderungen benachrichten, etc. Also macht man sich ein Interface [c]ByteEditorModel[/c] mit allen notwendigen Methoden.

Die Komponente selbst hört dann dem Modell zu und aktualisiert das Document der Textkomponente, aktualisiert den RowHeader und so weiter. Sie hört auf Änderungen in der Textkomponente und schreibt diese ins Modell. Außerdem sollte die neue Komponente zwischen byte-offset (4. Byte) und Document-Offset (Byte 4 beginnt am 8. Zeichen) in beiden Richtungen übersetzen können. Sowas wie [c]public int convertByteIndexToDocumentIndex(int index)[/c] und [c]public int convertDocumentIndexToByteIndex(int index)[/c].

So in etwa halt. 🙂

Ebenius
 
Zuletzt bearbeitet:
Hi,
erstmal danke für die Tipps.
Ich habe mich heute abend mal dran versucht meine JHexEditor Komponente zu schreiben. Musste aber leider feststellen, dass mir wohl noch sehr viele Grundlagen diesbezüglich fehlen :rtfm:
Ich wollte erstmal nur 2 textareas nebeneinander anzeigen lassen, nichtmal das habe ich hinbekommen 😳

Daher wollte ich mal fragen ob du vielleicht nen Tutorial kennst wo einem die Grundlagen mal ein bisschen näher gelegt werden oder, was natürlich noch besser wäre, ein "kleines" Grundgerüst posten könntest wie man sowas vernünftig aufzieht 🙂

Gruß,
Eike
 
Kann mir keiner nen kleinen Codeschnippsel geben, wo 2 JTextAreas auf einer eigenen JComponent eingefügt wurden? :bahnhof:
 
Das können sicher viele, aber wie genau sollen sich die JTextAreas verhalten? Beide gleichgroß? Dann JPanel mit GridLayout. Eines minimale Breite, ein anderes nimmt den Rest? JPanel mit BorderLayout. Beweglicher "Raumteiler" dazwischen? JSplitPane. Beide scrollbar? in JScrollPanes packen. Beide parallel zu scrollen? Separate JScrollBar.
 
Hi,
mir würds erstmal reichen wenn überhaupt irgendwas angezeigt werden würde, daran scheiterts bei mir ja schon.
Ich denke aber dass das BorderLayout wohl das richtige für mich wäre.
 
Java:
JPanel panel = new JPanel(new BoderLayout());
JTextArea area1 = new JTextArea("Lorem ipsum");
JTextArea area2 = new JTextArea("dolor sit amet");
panel.add(new JScrollPane(area1), Borderlayout.CENTER);
panel.add(new JScrollPane(area2), Borderlayout.EAST);
thePlaceWhereItShouldShowUp.add(panel);
 
Funktioniert bei mir leider nicht, ich habs so eingebaut:
Java:
public class JHexEditor extends JComponent{
    private JTextArea textArea;
    private JTextArea hexArea;

    private Document doc;

    public JHexEditor() {
        super();
        JPanel panel = new JPanel(new BorderLayout());

        textArea = new JTextArea();
        hexArea = new JTextArea();
        panel.add(textArea, BorderLayout.CENTER);
        panel.add(hexArea, BorderLayout.EAST);
        this.add(panel);

        updateUI();
    }
}
Wie auch schon bei meinen anderen Versuchen zeigt er mir nichts an, nur eine graue fläche.
Hinzufügen meiner Komponente mache ich mit:

Java:
    public JavaHexEditorView(SingleFrameApplication app) throws BadLocationException {
        super(app);
        initComponents();
        
        getFrame().add(new JHexEditor());

    }

Mache ich da was generelles falsch?
 
Da kann ich nur raten. Vielleicht:
Java:
        getFrame().getContentPane().add(new JHexEditor());
 
Ich denke das Problem liegt eher in der Komponente.

Folgender Code funktioniert nämlich ebenfalls nicht:

Java:
public class Testklasse {
    public static void main(String[] args) {
        JFrame frame = new JFrame();

        frame.add(new JHexEditor());
        frame.setVisible(true);
    }
}
 
Hinweis am Rande: Finger weg von [c]updateUI()[/c]. Diese Methode ist zum kompletten Neu-Initialisieren des UI-Delegates und für nichts anderes gedacht.

Ebenius
 

Zurück
Oben