I'm attempting to create an IM program as a sort of hobby project. I've been experimenting with UI designs and have been trying to get this prototype for the actual message display working.
Currently, the frame is set up like so;
- The JFrame content pane is set to a JPanel which utilizes a BoxLayout using Y_AXIS.
- The content panel contains the TextMessage objects which I would like to display, added to the content pane individually.
The TextMessage object is setup like so;
- The message and sender string are stored inside of a TextMessage object extending JTextPane and utilizing a StyledDocument for formatting.
- The TextMessage is placed inside of a JPanel in order to allow proper placement of the object within the BoxLayout. The JPanel is set to a FlowLayout which pins the TextMessage object against either edge of the JPanel, depending on a boolean value.
Thus far, everything is working as I would like it to, with one notable exception. When I resize the JFrame, the TextMessage objects do not resize and instead simply disappear off the edge of the screen.
Expected Result:
The actual Result:
The JFrame Class:
public class NewMain extends JFrame {
public NewMain() {
setTitle("SparrowIM Chat Bubble");
setPreferredSize(new Dimension(880, 550));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(true);
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
setContentPane(panel);
add(new TextMessage("Hey, man. What's up?", "Jnk1296", true));
add(new TextMessage("Eh, nothing much.", "KeepJ96", false));
add(new TextMessage("Wbu? Anything new going on with you?", "KeepJ96", false));
add(new TextMessage("Nah, not really. Got a job interview coming up in a few " +
"days, though. Sorta excited for that, but sorta not. " +
"Other than that, life as usual. xD", "Jnk1296", true));
add(new TextMessage("lol Sounds good.", "KeepJ96", false));
add(new TextMessage("Yeah. How's the wife and kids, though?", "Jnk1296", true));
add(new TextMessage("Sarah still griping at you to get the roof patched up?", "Jnk1296", true));
add(new TextMessage("lol you could say that...", "KeepJ96", false));
pack();
setVisible(true);
}
public static void main(String[] args) {
new NewMain();
}
}
TextMessage Object (JPanel Container for TextMessageContent):
public class TextMessage extends JPanel {
private TextMessageContent content;
public TextMessage(String sender, String message, boolean localMessage) {
setBorder(new EmptyBorder(5, 5, 5, 5));
if (localMessage) {
setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
} else {
setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
}
this.content = new TextMessageContent(sender, message, localMessage);
add(content);
}
public TextMessageContent getContent() {
return this.content;
}
}
TextMessageContent Class: (JTextPane)
public class TextMessageContent extends JTextPane {
private static final long serialVersionUID = -8296129524381168509L;
private String sender;
private String message;
private boolean isClient;
private Image background;
public TextMessageContent(String message, String sender, boolean isClient) {
// Define Data Points
this.message = message;
this.sender = sender;
this.isClient = isClient;
this.setEditable(false);
this.setOpaque(false);
this.setBorder(new EmptyBorder(7, 7, 7, 7));
// Fetch Background Image (Hard Location Temporary)
try {
if (this.isClient) {
background = ImageIO.read(
new File("/home/jacob/Desktop/orange.png"));
} else {
background = ImageIO.read(
new File("/home/jacob/Desktop/Green.png"));
}
} catch (Exception e) { return; }
// Create Text Styles
StyledDocument doc = getStyledDocument();
// Create Default Base Style
Style def = StyleContext.getDefaultStyleContext()
.getStyle(StyleContext.DEFAULT_STYLE);
Style regular = doc.addStyle("regular", def);
// Create Body Style
Style body = doc.addStyle("message", regular);
StyleConstants.setFontFamily(body, "Verdana");
StyleConstants.setFontSize(body, 12);
// Create Sender Style
Style foot = doc.addStyle("sender", body);
StyleConstants.setFontSize(foot, 9);
// Build Document
try {
doc.insertString(0, this.message + "\n", body);
doc.insertString(doc.getLength(), this.sender + " - " +
getSystemTime(), foot);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
@Override
public void paintComponent(Graphics g) {
background = ImageUtil.stretch(background, new Insets(5, 5, 5, 5),
new Dimension(getWidth(), getHeight()),
BufferedImage.TYPE_INT_ARGB);
g.drawImage(background, 0, 0, null);
super.paintComponent(g);
}
private String getSystemTime() {
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("h:mm a");
return sdf.format(cal.getTime());
}
}
I've read about simply adding the JTextPane directly to the containers and whatnot, but with this set up, the JPanel wrapping around the text message content is necessary to keep the BoxLayout of the content pane from making the Text Messages fill the entire panel.
Any suggestions?