java - JTextArea suddenly resizes upon dialog resizing -


i have problem using jtextarea. actual setup different, effects remain. here image of problem:

enter image description here

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:

enter image description here

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...

enter image description here

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...

enter image description here

my code...

enter image description here

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