12. april 2003 - 10:05Der er
13 kommentarer og 1 løsning
Bredde på en String
Jeg har brug for at vide hvor lang en given String er, så jeg ikke skriver længere end til et JTextField's bredde. Til det formål benytter jeg følgende kode, som jeg har forstået er den mest nøjagtige "bredde"-bestemmelse:
ud fra bounds kan jeg så få bredden på strengen. Bredden er bare ikke nøjagtig, for det er ikke altid at jeg kan skrive helt udt til enden på tekstfeltet, og andre gange "smutter" den en eller to bogstaver forbi enden.(Jeg checker bredden med en KeyListener)
Er der en mere nøjagtig breddebestemmelse, eller er der en anden måde at sikre, at man ikke kan skrive længere end til tekstfeltets bredde?
Jeg prøvede dit eksempel til at starte med, men det var også upræcist. Så læste jeg i Javadoc'en at TextLayout, skulle beregne længden meget præcist. Den var også en smule bedre, men stadig ikke præcis nok til at kun at skrive til enden af tekstfeltet.
Der skrives lidt for kort eller lidt for langt, men indimellem også tilpas, men jeg håber selvfølgelig på noget der er tilpas hvergang.
så kan jeg ikke hjælpe dig. jeg har aldrig nogensinde haft problemer med fontmetrics. er det en standard font du bruger? den kan jo være din font ikke beregner bredden godt nok på den enkelte Glyph.
Tjaa, jeg har ihvertfald ikke defineret nogen font, så java bruger vel en standard.
Har du lavet noget der sikrer at man ikke kan skrive ud over et JTextField's bredde med fontmetrics, så vil jeg meget gerne se koden, for JEG kan ikke få det til at virke optimalt.
Jeg kan selvfølgelig bare gøre som jeg gør nu. Skrive i et tekstfelt, og så se om der skrives ud over kanten, og hvis der gør så trække lidt fra (eller lægge til) den værdi som fontmetrics giver mig.
Det virker bare lidt bøvlet, og ikke særligt stilfuldt hvis man skal håndtere mange tekstfelter. Det vare nemmere hvis en metode gjorde arbejdet for mig og det virkede ens hver gang.
carsten >> Jeg har afprøvet din kode, og den virker lige så godt som min egen kode. For at være sikker på at der ikke skrives ud over enden, har du trukket 25 fra teksfeltets bredde. Det er også den løsning jeg selv har fundet frem til, men jeg ville jo gerne have noget generel kode der kunne sikre mig at det blev fyldt helt ud i tekstfeltet hverken mere eller mindre, uden at skulle tænke på om der skal trækkes lidt fra eller lægges til.
Følgende kode er den jeg selv har fundet mest hensynsfuld, men den tillader heller ikke noget fast, for jeg skal lægge 12 til teksten, og der kan indimellem godt være ét bogstav mere, men hvis jeg ændrer det, forsvinder der måske et bogstav ud ved næste ord der skrives. Du kan jo selv prøve det ved at gøre framen større eller mindre.
Det må da være muligt at finde noget der er helt nøjagtigt hvergang.
public class Test extends JFrame implements KeyListener { private JTextField tekstfelt;
public Test() { setSize(120,50); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
tekstfelt = new JTextField(""); getContentPane().add(tekstfelt); tekstfelt.addKeyListener(this); }
public void keyReleased(KeyEvent e){} public void keyPressed(KeyEvent e){} public void keyTyped(KeyEvent e) { if(tekstfelt.getText().length() > 0) { if(tekstfelt.getSize().width > getFontMetrics(getFont()).stringWidth(tekstfelt.getText())+12) return; else { if(e.getKeyChar() == '')//char for backspace(kender ikke tal-definitionen) return; else e.consume(); }}}
public static void main(String args[]) { Test test = new Test(); test.setVisible(true); } }
Jeg havde lavet en stor bøf, defineret min egen font og brugt den til at måle tekstlængden, jeg modificeret min udgave, den er ihverfald væsentlig bedre nu, om det er godt nok ved jeg ikke, men nu bruger jeg ihverfald den aktuelle font.
Jeg tror ikke du slipper for at trække noget(i mit sidste tilfælde kun 1)
Jeg har ikke testet din endnu, men det vil gøre! Carsten
Da tekstfeltets bredde måles i 'int' og en tekst's længde i float, skal der grundet den casting du er nødt til at foretage, trækkes lidt fra og det er i mit sidste tilfælde kun 1.
I princippet er jeg egentlig ligeglad med om der skal trækkes 1 eller 2000 fra, ideen var at lave noget der ikke skal tilpasses manuelt ved at prøve sig frem, det virker ikke særligt proffesionelt. Desuden kan jeg sagtens få skriften i dit andet eksempel til at smutte 2-3 bogstaver ud over feltlængden på en standard-font, så jeg er faktisk ikke kommet videre end da jeg stillede spørgsmålet.
Hvis nedenstående eksempel ikke fungerer hos dig, er jeg villig til at give op!!
Kompiler de 2 classer og prøv, du for IKKE lov til at indsætte flere tegn end dit textfelt er bredt!
public class TestTextLength extends javax.swing.JFrame {
public TestTextLength() { initComponents(); Text t = new Text(10, jTextField1.getGraphics(), jTextField1.getFont(), jTextField1); jTextField1.setDocument(t.createDefaultModel()); }
private void initComponents() { jTextField1 = new javax.swing.JTextField();
Hvis jeg starter med et m og fylder resten op med i, burde det sidste i ikke skrives med, fordi det første m forsvinder næsten halvt. Desuden trækker du jo stadigvæk 1 fra, så alt i alt må jeg indrømme at jeg ikke kan bruge din kode, og den er desuden også ret omfattende for at klare en så "lille" operation. Jeg bibeholder min egen kode, og slår mig til tåls med at problemet ikke kan løses pt.
Desuden er jeg ikke enig i at der skal laves en typecast for at sammenligne en float med en int. Hvis float'en er større end int'en så er den større uanset hvad.
Men da spørgsmålet nu har været åbent forholdsvis længe får du pointene for din ihærdige indsats, så du også i fremtiden har lyst til at deltage i mine spørgsmål.
Du er stadig nødt til at trække, da et default tekstfelt er markeret, d.v.s. feltets ydre og indre mål IKKE er ens og getWidth() måler det ydre mål - alternativt kan du bruge "jTextField1.setBorder(null);" så behøver du ikke at trække noget fra.
Jeg kan godt se, at gør man som du siger forsvinder halvdelen af m'et, så teksfeltets grænse er altså tykkere end 1, retter du til 3 er der masser af plads
Det kan godt være du synes operationen er "lille", men class Text skal bare laves én gang, resten af livet kan den anvendes men "kun" 2 linier Text t = new Text(10, jTextField1.getGraphics(), jTextField1.getFont(), jTextField1); jTextField1.setDocument(t.createDefaultModel());
M.h.t. float/int - ja, gammel vane med at sammenligne "identiske" typer!
Jeg synes lige du skulle have den helt perfekte udgave, om det skyldes ihærdighed ved jeg ikke, men jeg kan selv bruge din ide.
Finder selv tekstfeltets grænsetykkelse.
public class TestTextLength extends javax.swing.JFrame {
public TestTextLength() { initComponents(); MaxTextLength t = new MaxTextLength(10, jTextField1); jTextField1.setDocument(t.createDefaultModel()); t = new javatest.MaxTextLength(10, jTextField2); jTextField2.setDocument(t.createDefaultModel()); t = new javatest.MaxTextLength(10, jTextField3); jTextField3.setDocument(t.createDefaultModel());
pack(); }
private void initComponents() { jTextField1 = new javax.swing.JTextField(); jTextField2 = new javax.swing.JTextField(); jTextField3 = new javax.swing.JTextField();
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.