i have problem using jtextarea
. actual setup different, effects remain. here image of problem:
the moment owning jdialog
resizes 1 pixel below jtextarea
's require preferred sizes, text areas resize. in actual setup, grow in height. using gridbaglayout
, seems happen in other layouts. why this?
here easy-to-compile code reproduce above effect.
import java.awt.*; import java.awt.event.*; import java.text.simpledateformat; import java.util.date; import javax.swing.*; import javax.swing.text.jtextcomponent; public class textdemo extends jdialog implements actionlistener { private static final long serialversionuid = -589374238138963529l; protected jtextfield textfield; protected jtextarea textarea; private final static string newline = "\n"; private static final java.awt.dimension screensize = java.awt.toolkit.getdefaulttoolkit().getscreensize(); private static final java.awt.point screencenter = new java.awt.point(screensize.width/2,screensize.height/2); public textdemo(window owner, string shortmessage, string message, jcomponent accessory) { super(owner); settitle("test"); setdefaultcloseoperation(jdialog.hide_on_close); icon icon = uimanager.geticon("optionpane.warningicon"); jtextarea shorttext = makemultilinelabel(true); shorttext.setborder(borderfactory.createetchedborder()); shorttext.setfont(shorttext.getfont().derivefont(font.bold)); shorttext.setrows(2); shorttext.setcolumns(20); shorttext.settext(shortmessage); jtextarea messagetext = makemultilinelabel(true); messagetext.setborder(borderfactory.createetchedborder()); messagetext.setfont(shorttext.getfont().derivefont(font.plain)); messagetext.setrows(4); messagetext.setcolumns(20); messagetext.settext(message); jpanel buttonpanel = new jpanel(); buttonpanel.add(new jbutton("ok")); buttonpanel.add(new jbutton("cancel")); jpanel contentpanel = new jpanel(); contentpanel.setopaque(true); contentpanel.setborder(borderfactory.createemptyborder(10, 10, 8, 9)); contentpanel.setlayout(new gridbaglayout()); gridbagconstraints c; c = new gridbagconstraints(); c.gridx = 0; c.gridy = 0; c.anchor = gridbagconstraints.first_line_start; c.gridheight = 2; contentpanel.add(new jlabel(icon), c); c = new gridbagconstraints(); c.gridx = 1; c.gridy = 0; c.fill = gridbagconstraints.both; c.weighty = 1.0; c.weightx = 1.0; contentpanel.add(shorttext, c); c = new gridbagconstraints(); c.gridx = 1; c.gridy = 1; c.fill = gridbagconstraints.both; c.weighty = 1.0; c.weightx = 1.0; contentpanel.add(messagetext, c); if (accessory != null) { c = new gridbagconstraints(); c.gridx = 0; c.gridy = 2; c.gridwidth = 2; c.fill = gridbagconstraints.both; c.weighty = 1.0; c.weightx = 1.0; contentpanel.add(accessory, c); } c = new gridbagconstraints(); c.gridwidth = 2; c.gridx = 0; c.gridy = 3; contentpanel.add(buttonpanel, c); setcontentpane(contentpanel); } public void actionperformed(actionevent evt) { string text = textfield.gettext(); textarea.append(text + newline); textfield.selectall(); //make sure new text visible, if there //was selection in text area. textarea.setcaretposition(textarea.getdocument().getlength()); } /** * create gui , show it. thread safety, * method should invoked * event dispatch thread. */ private static void createandshowgui() { //create , set window. jframe frame = new jframe("textdemo"); frame.setdefaultcloseoperation(jframe.exit_on_close); try { throw new exception("test"); } catch (exception e) { textdemo t = new textdemo(frame, "you won't away this!", "alert! alert! chocy nut bar has been removed without payment!" + " chocy nut bar... has been removed! without payment! alert, alert!", getstacktracetextarea(e)); //display window. frame.pack(); frame.setlocation(screencenter.x - frame.getsize().width/2, screencenter.y - frame.getsize().height/2); frame.setvisible(true); t.setmodal(true); t.pack(); t.setlocation(getpos(t, t.getowner())); t.setvisible(true); } } protected static jcomponent getstacktracetextarea(throwable exception) { jtextarea textarea = new jtextarea(); textarea.seteditable(false); textarea.setlinewrap(false); textarea.append(gettracemessage(exception)); textarea.setcaretposition(0); jscrollpane scroll = new jscrollpane(textarea); scroll.sethorizontalscrollbarpolicy(jscrollpane.horizontal_scrollbar_always); scroll.setverticalscrollbarpolicy(jscrollpane.vertical_scrollbar_always); scroll.setpreferredsize(new dimension(50, 140)); return scroll; } private static final string gettracemessage(throwable exception) { stringbuilder out = new stringbuilder((new simpledateformat("yyyy/mm/dd hh:mm:ss")) .format(new date())+": unhandled exception: \n" +exception.tostring()+"\n\nstack trace:\n"); stacktraceelement[] stacktrace = exception.getstacktrace(); (int = 0; < stacktrace.length; i++) { string toappend = stacktrace[i].tostring(); if (i != stacktrace.length-1) toappend += "\n"; out.append(toappend); } return out.tostring(); } public static final jtextarea makemultilinelabel(boolean selectable) { jtextarea area = new jtextarea(); area.setwrapstyleword(true); area.setlinewrap(true); area.setfont(uimanager.getfont("label.font")); area.seteditable(false); area.setcursor(null); area.setopaque(false); area.setfocusable(selectable); area.setalignmentx(jtextcomponent.left_alignment); area.setminimumsize(new dimension(0,0)); return area; } private static point getpos(jdialog d, window w) { return new point(w.getx()+(w.getwidth ()-d.getwidth ())/2, w.gety()+(w.getheight()-d.getheight())/2); } public static void main(string[] args) { //schedule job event dispatch thread: //creating , showing application's gui. javax.swing.swingutilities.invokelater(new runnable() { public void run() { createandshowgui(); } }); } }
edit changes suggested implemented, problem still remains:
the problem you're witnessing gridbaglayout
trying deal situation it's not able honour preferredsize
of component, reverts using components minimumsize
instead...
you use gridbagconstraints#weightx
property force component fill it's columns width...
c = new gridbagconstraints(); c.gridx = 1; c.gridy = 0; c.fill = gridbagconstraints.both; c.weighty = 1.0; c.weightx = 1.0; contentpanel.add(shorttext, c); c = new gridbagconstraints(); c.gridx = 1; c.gridy = 1; c.fill = gridbagconstraints.both; c.weighty = 1.0; c.weightx = 1.0; contentpanel.add(messagetext, c);
this won't stop shrinking, stop "snapping" 1 size another.
try , avoid using setpreferredsize
, check out should avoid use of set(preferred|maximum|minimum)size methods in java swing? more details. instead use rows
, columns
properties of jtextarea
...
shorttext.setrows(2); // example
personally, wrap jtextarea
's in jscrollpane
, becomes, slightly, less important having enough room each
feed back...
now, question out of context, appears me going lot of effort little gain.
for example, instead, use joptionpane
, take advantage of swing's html rendering capabilities...
import java.awt.eventqueue; import javax.swing.joptionpane; import javax.swing.uimanager; import javax.swing.unsupportedlookandfeelexception; public class optionpanetest { public static void main(string[] args) { new optionpanetest(); } public optionpanetest() { eventqueue.invokelater(new runnable() { @override public void run() { try { uimanager.setlookandfeel(uimanager.getsystemlookandfeelclassname()); } catch (classnotfoundexception | instantiationexception | illegalaccessexception | unsupportedlookandfeelexception ex) { } stringbuilder sb = new stringbuilder(128); sb.append("<html><b><p align=center>you won't away this!</p></b><br>"); sb.append("alert! alert! chocy nut bar has been removed without payment!"); sb.append("<br>a chocy nut bar... has been removed! without payment! alert, alert!"); joptionpane.showmessagedialog(null, sb.tostring(), "alert", joptionpane.warning_message); } }); } }
also...
i think you'll find using...
frame.setlocationrelativeto(null);
much easier , less time consuming then...
frame.setlocation(screencenter.x - frame.getsize().width / 2, screencenter.y - frame.getsize().height / 2);
this mean can use t.setlocationrelativeto(frame)
well...
oh, +1 red dwarf reference ;)
updated updates question
the solution still (basically) same, use jtextarea#setrows
, jtextarea#setcolumns
...
your code...
my code...
jtextarea shorttext = makemultilinelabel(true); shorttext.setborder(borderfactory.createetchedborder()); shorttext.setfont(shorttext.getfont().derivefont(font.bold)); // fontmetrics fm = shorttext.getfontmetrics( // shorttext.getfont()); // shorttext.setpreferredsize(new dimension( // math.min(fm.stringwidth(shortmessage), 300), // fm.getheight())); shorttext.setrows(2); shorttext.setcolumns(20); shorttext.settext(shortmessage); jtextarea messagetext = makemultilinelabel(true); messagetext.setborder(borderfactory.createetchedborder()); messagetext.setfont(shorttext.getfont().derivefont(font.plain)); // fm = messagetext.getfontmetrics( // messagetext.getfont()); // messagetext.setpreferredsize(new dimension( // math.min(fm.stringwidth(message), 300), // fm.getheight())); messagetext.setrows(4); messagetext.setcolumns(20); messagetext.settext(message);
you may want take @ swingx's jxerrordialog
well