Avatar billede fbehrend Nybegynder
23. februar 2004 - 11:00 Der er 19 kommentarer og
2 løsninger

Readonly JTextField

Hej

Jeg skal bruge et readonly JTextField, hvor det er muligt at markere tekst i og lave en ctrl-c (copy), men hvor det ikke er muligt at paste noget ind i med ctrl-v.

Jeg har leget lidt med ideen om at overskrive
insertString(int offset, String str, AttributeSet a), til en
tom metode. Så kan jeg ganske rigtigt ikke paste ind i
document modellen, men jeg kan heller ikke bruge
setText(String text)

Er der nogle der har en god ide ???
Avatar billede arne_v Ekspert
23. februar 2004 - 11:11 #1
setEditable(false) kan ikke løse dit problem ?
Avatar billede fbehrend Nybegynder
23. februar 2004 - 12:16 #2
Nej setEditable løser ikke mit problem.

Ved setEditable kan der ikke markeres tekst i feltet.

Mit Tekstfelt skal se ud som et almindeligt JTextField, som har setEditable(true), og man skal kunne foretage almindelige text actions i feltet, de skal ikke disables, dvs at man skal kunne trykke ctrl ned og markere tekst med piltasterne, og man skal kunne trykke ctrl-c for at copiere teksten.

Det eneste man ikke må er at skrive i feltet og at paste ind i feltet.
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 13:57 #3
Jeg kan nu altså godt markere tekst og bruge ctrl-c, når setEditable(false) er kørt!
Cursoren ændre sig bare ikke, som den normalt vil gøre over et JTextField!
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 14:00 #4
Hvis du gør følgende kan du ikke skrive i textfeltet, men du kan godt kopiere fra det.
Jeg har ændret cursoren, så den ligner den der normalt er over et textfelt, og sat baggrunden til hvid.

JTextField textField = new JTextField();
textField.setText("TEST");
textField.setEditable(false);
textField.setCursor(new Cursor(Cursor.TEXT_CURSOR));
textField.setBackground(Color.white);
Avatar billede _carsten Nybegynder
23. februar 2004 - 14:06 #5
Ellers både denne vel løse det (ikke testet)

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

public class MyTextField extends JTextField implements KeyListener{
    public MyTextField()    {
            super();
    }
   
      public void keyTyped(KeyEvent e){
        // disable alt andet end CRTL +V
        int keycode = event.getKeyCode();
        int modifiers = event.getModifiers();
           
        if (modifiers != KeyEvent.CTRL_MASK &&
            keycode != KeyEvent.VK_V)
            e.consume();
      }
       
      public void keyPressed(KeyEvent e){
      }
       
      public void keyReleased(KeyEvent e){
      }
    }
}
Avatar billede _carsten Nybegynder
23. februar 2004 - 14:07 #6
keycode != KeyEvent.VK_V)

Skulle selvfølgelig være
keycode != KeyEvent.VK_C)
Avatar billede fbehrend Nybegynder
23. februar 2004 - 14:51 #7
Til Carsten
Den løsning havde jeg også tænkt på, men jeg vil helst undgå at løse det med low lvl events.

Til MikkelBM
Din ide virker rigtigt nok, det at man sætter cursoren gør åbentbart at man kan markere tekst i feltet, problemet er bare at jeg ikke får nogen cursor.

Til Begge
Jeg havde nu mere forestillet mig noget i retning af at implementere et document filter (javax.swing.text.DocumentFilter), som nu understøttes i 1.4.
Det sættes med setDocumentFilter() som findes på AbstractDocument.
Det ville give en ren indkapsling, hvor de andre løsninger på en eller anden måde virker lidt som et hack :)

Den første der kommer med et forslag der virker får alle point (Det skal lige siges at jeg selv også arbejder på sagen, og at det er noget der haster) :)
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 15:13 #8
Hmmm. Mht DocumentFilter må jeg nok melde pas - det har jeg ikke rigtig arbejdet med.
Men hvad mener du med:
"problemet er bare at jeg ikke får nogen cursor."

Det virker perfekt ved mig. Lige så snart jeg bevæger musen over JTextField skifter cursoren til text-cursor.

Om det er den pæneste måde at løse det på, ved jeg ikke. Men jeg vil mene, at når det nu ikke er større, at det sagtens kan forsvares.
Avatar billede fbehrend Nybegynder
23. februar 2004 - 15:19 #9
Det er ikke muse cursoren jeg snakker om, den skifter rigtigt nok.

Problemet er at der ikke kommer en cursor inde i tekstfeltet, brugeren skal kunne se hvor cursoren er i tekstfeltet.
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 15:22 #10
Ah... ok.
Skal det så også være muligt at flytte cursoren med f.eks. piletasterne?
Avatar billede _carsten Nybegynder
23. februar 2004 - 15:22 #11
Jeg kan faktisk ikke rigtig se hvordan det skal kunne lade sig gøre med DocumentFilter, jeg mener ikke at DocumentFilter tager hensyn til om input sker via tastaturet oder was

Jeg hælder stadig mere til min egen løsning (lidt endnu).
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 15:36 #12
Hvis du tilføjer:

textField.getCaret().setVisible(true);

Til det jeg tidligere skrev, så skulle det virke!
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 15:41 #13
Den skal så sættes ind før du definerer cursoren:

JTextField textField = new JTextField();
textField.setText("TEST");
textField.setBackground(Color.white);
textField.setEditable(false);
textField.getCaret().setVisible(true);
textField.setCursor(new Cursor(Cursor.TEXT_CURSOR));
Avatar billede fbehrend Nybegynder
23. februar 2004 - 16:13 #14
Til Mikkel

Det virker lidt underligt når jeg sætter getCaret().setVisible(true)

For det første hvis jeg har 3 instancer af mit tekst felt kommer der en cursor i alle 3 tekstfelter, når jeg stater applikationen op.

Første gang jeg vælger et readonly felt og derefter flytter focus, kommer der aldrig en cursor igen, og dette er selvom at readonly feltet modtager focus.
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 16:30 #15
Ja, det kan jeg da egentlig godt se.

Du kan komme uden om det, hvis du tilføjer en FocusListener til dine textfields:

private class MyFocusListener implements FocusListener
{
    private JTextField field;
       
    public MyFocusListener(JTextField field)
    {
        this.field = field;
    }   
       
    public void focusLost(FocusEvent e)
    {
        field.getCaret().setVisible(false);    
    }
    public void focusGained(FocusEvent e)
    {
        field.getCaret().setVisible(true);    
    }
}

Og så:

textField1.addFocusListener(new MyFocusListener(textField1));
textField2.addFocusListener(new MyFocusListener(textField2));
textField3.addFocusListener(new MyFocusListener(textField3));

Det virker i hvert fald, men om det er for omstændigt og måske ikke så pænt, ved jeg ikke hvad jeg skal sige til :)
Avatar billede _carsten Nybegynder
23. februar 2004 - 17:30 #16
> Mikkelbm: Jeg kan ikke se at din måde at gøre det på skulle være mindre pæn eller omstændigt, det vil være langt mere omstændigt at implementere DocumentFilter().
Tværtimod synes jeg det er nem og hurtig måde at komme videre på, min måde kræver lidt modifikation i f.h.t til min tidligere kommentar

Her et eksempel hvor både min og mikkelbm's måde anvendes.
For mig at de lige besværlige/nemme


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

public class Exp468642 extends javax.swing.JFrame {
   
    public Exp468642() {
        initComponents();
    }
   
    private void initComponents() {

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });
       
        mikkel = new Mikkel();
        mikkel2 = new Mikkel();
        carsten = new Carsten();
        getContentPane().setLayout(new java.awt.FlowLayout());
        getContentPane().add(mikkel);
        getContentPane().add(mikkel2);
        getContentPane().add(carsten);
       
        pack();
    }
   
    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }
   
    public static void main(String args[]) {
        new Exp468642().show();
    }
   
    private Carsten carsten;
    private Mikkel mikkel, mikkel2;
}



class Carsten extends JTextField implements KeyListener{
    public Carsten(){
        super("Carsten");
        setPreferredSize(new Dimension(100,18));
        addKeyListener(this);
    }
   
    public void keyTyped(KeyEvent e){
        if ( e.getKeyCode() != KeyEvent.VK_CONTROL ){
          e.consume();
        }         
    }

    public void keyPressed(KeyEvent e){
        if( e.getKeyCode() != KeyEvent.VK_C ){
            e.consume();
        }
    }

    public void keyReleased(KeyEvent e){
    }
}




class Mikkel  extends JTextField implements FocusListener{
    public Mikkel(){
        setText("Mikkel");
        setBackground(Color.white);
        setEditable(false);
        addFocusListener(this);
        setPreferredSize(new Dimension(100,18));
    }
   
    public void focusGained(java.awt.event.FocusEvent focusEvent) {
        getCaret().setVisible(true);
        setCursor(new Cursor(Cursor.TEXT_CURSOR));
    }
   
    public void focusLost(java.awt.event.FocusEvent focusEvent) {
        getCaret().setVisible(false);
    }
}
Avatar billede mikkelbm Nybegynder
23. februar 2004 - 17:40 #17
Som jeg skrev tidligere kender jeg ikke til DocumentFilter, derfor vidste jeg ikke om det kunne gøres mere elegant :)

Men om det skal være din eller min kode må være op til fbehrend.
Avatar billede mikkelbm Nybegynder
24. februar 2004 - 22:56 #18
Fik du løst problemet?
Avatar billede fbehrend Nybegynder
25. februar 2004 - 00:48 #19
Jeg endte op med at disable de TextActions jeg ikke skulle bruge, så som pasteAction, med

Action a = (Action)getActionMap().get(DefaultEditorKit.pasteAction);
a.setEnabled(false);

Jeg ville helst undgå en løsning med low level events, så som KeyEvent og FocusEvent.

Jeg er glad for at i kom med så meget feedback, og jeg vil gerne dele pointene ud mellem jer, selvom jeg selv kom med løsningen. Problemet er bare at jeg ikke ved hvordan jeg deler point (Jeg er ret ny herinde)
Avatar billede mikkelbm Nybegynder
25. februar 2004 - 10:33 #20
Du beder Carsten om at lægge et svar - så markerer du begge to og trykke acceptér svar.
Avatar billede _carsten Nybegynder
25. februar 2004 - 11:37 #21
Der kommer et svar her
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester