So this is my situation:
I have a timer and it updates values in the background until a value has reached a certain point.
But in order for me to see each update of value I currently have to add in a
"new ListWindow();" statement in my for loop.
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
/**
* Write a description of class Timing here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Timing
{
/**
* Constructor for objects of class Timing
*/
public static void Timer()
{
Timer timer = new Timer(250, new TimerListener());
timer.start();
}
private static class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
while(valX != 100)
{
Timer();
MainProg.valX += 5;
// new ListWindow(); //statement goes here. it creates a new window
//each time it updates the value.
}
}
}
}
My problem is: I do not want a new window. I want the list that the value comes from (see below) to update its value and refresh the list in the current window. perhaps on a button click.
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Component.*;
/**
* Write a description of class ListWindow here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class ListWindow extends JFrame
{
private JPanel StatsPanel; //holds stats
private JPanel ButtonPanel; //holds stats
private JList StatList; //inventory
private JButton RefreshButton; // a button
private String[] Stats =
{"Stuff " + Stuff, "Value " + valX, "Test " + per};
/**
* Constructor
*/
public ListWindow()
{
setTitle("STATS");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
buildStatsPanel();
buildButtonPanel();
RefreshButton.addActionListener(new ButtonListener());
add(StatsPanel, BorderLayout.CENTER);
add(ButtonPanel, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public void buildStatsPanel()
{
StatsPanel = new JPanel();
StatList = new JList(Stats);
StatList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
StatsPanel.add(StatList);
}
public void buildButtonPanel()
{
ButtonPanel = new JPanel();
RefreshButton = new JButton("Refresh");
ButtonPanel.add(RefreshButton);
}
private class ButtonListener
implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String actionCommand = e.getActionCommand();
if(actionCommand.equals("Refresh"))
{
pack();
invalidate();
validate();
}
}
}
public void RunMain(String[] args)
{
new ListWindow();
}
}
Also: this is my main method where I run things from. You should also notice that I have main methods in my other two snippets I pasted here. I did this so I could run things individually for quick debugging and future use.
/**
* Write a description of class MainProg here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class MainProg
{
public static int stuff = 100;
public static int valX = 0;
public static int per = 100;
/**
* Constructor for objects of class Game
*/
public static void main()
{
new MoveWindow();
new ListWindow();
while (valX != 100)
{
Timing.Timer();
}
}
}
I am very new to java, i have looked for other solutions and was unable to find what I think i need. Perhaps I did find it, and did not recognize it as a solution.
All help is appreciated, thanks in advance.
Call a function that updates the list (the default JList ListModel used when supplying a Object array is rather inflexible and you may need to use a different ListModel rather than the default) with the new value.
Related
package gameprojekt;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
//The GameWindow class holds the window
public class Game extends JFrame {
/*Global variable declaration*/
private int width;
private int height;
private int windowXPos;
private int windowYPos;
public static String p1 = "Player1";
public static String p2 = "Player2";
public static int playerScore = 0;
public static int oponentScore = 0;
public static int player1X;
public static int Player1Y;
public static int player2X;
public static int Player2Y;
private static boolean running = true;
public static int status = 0;
public static JFrame frame = new JFrame("Pong");
//public TestDrawPanel testPanel = new TestDrawPanel();
public static int getStatus() {
return status;
}
public static void setStatus(int status) {
Game.status = status;
}
// ------------------------------------------------------------
/**
* Creates a new JFrame window with the given size and
* center it based on the screen resolution
*/
public static final long serialVersionUID = 1L;
public Game() {
/*Local variable declaration*/
//JFrame frame = new JFrame("Pong");
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
width = (int)dim.getWidth();
height = (int)dim.getHeight();
windowXPos = width / 2 - (width / 2) / 2;
windowYPos = height / 2 - (height / 2) / 2;
// ------------------------------------------------------------
// Set size, half of the screen resolution
frame.setSize(width/2, height/2);
// Allign the window to the users resolution
frame.setLocation(windowXPos, windowYPos);
frame.setVisible(true);
frame.setResizable(false);
// By exiting the window using "X" all relevant data is closed
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
/* zum Testen auskommentiert
#Override
public void paint(Graphics g) {
System.out.println("test");
this.drawPlayer(g);
}*/
/**
* Draw the Player on the given location and with the given size
* #param g Graphics object
*/
public void drawPlayer(Graphics g) {
}
private static void gameLoop() {
Menue m = new Menue();
m.loadMenue(frame);
while (running) {
if (m.isStartPressed()) {
System.out.println("test");
}
}
}
/**
* Create the game and initialize the gameplay
*/
public static void main(String[] args) {
/*Variable declaration*/
// ------------------------------------------------------------
Game game = new Game();
game.gameLoop();
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package gameprojekt;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
*
*/
public class Menue {
/* Global variable declaration */
private int widthMenue;
private int heightMenue;
private String start = "Start";
private String highscores = "Highscores";
private boolean startPressed = false;
public JButton bStart = new JButton(start);
public JButton bScore = new JButton(highscores);
// ----------------------------------------------------
public boolean isStartPressed() {
return startPressed;
}
public void setStartPressed(boolean startPressed) {
this.startPressed = startPressed;
}
public int getWidthMenue() {
return widthMenue;
}
public void setwidthMenue(int widthMenue) {
this.widthMenue = widthMenue;
}
public int getheightMenue() {
return heightMenue;
}
public void setheightMenue(int heightMenue) {
this.heightMenue = heightMenue;
}
public void loadMenue(JFrame j) {
JPanel menue = new JPanel();
LayoutManager border = new BorderLayout();
menue.setLayout(border);
menue.setBackground(Color.black);
bStart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setStartPressed(true);
}
});
menue.add(bStart, BorderLayout.LINE_START);
menue.add(bScore, BorderLayout.LINE_END);
j.getContentPane().add(menue);
}
}
Hi I'm having a problem that the variable startPressed seems to be getting ignored. If the button start is pressed the variable startPressed is set to true but the if statement in this while loop doesn't react to the new value:
while (running) {
if (m.isStartPressed()) {
System.out.println("test");
}
}
If I add System.out.println or Thread.sleep inside the loop then the if statement recognizes the value and is giving me the output.
I thought maybe there is a main problem in the programming structure or Java is too slow. Any ideas?
Thanks!
Your main problem is that your startPressed variable is not made volatile, and thus changing it in one thread may not be reflected in another thread. Change this and you'll see that your start button changes this variable appropriately:
private volatile boolean startPressed = false;
Your game loop shouldn't be as it flies in the face of Swing threading rules. Why not use a Swing Timer (my preference) or if you need your own roll-your own loop, then doing so in a background thread. Also consider making startPressed a "bound" variable, one that when changed tells any property change listeners that its state has been changed. This would be better than constantly polling its value.
Another comment: your code overuses statics and would be much better organized if you got rid of most of your static modifiers.
When you do something like
while(running) {
...
}
it means, that this loop is executed over and over again, nothing stops it, it gets executed as fast as your PC can do it. And therefore, it tends to block everything else. So yes, your program structure is the problem. Try to execute your game-loop in a separate thread. This thread can then update your view from time to time. Maybe think about to pause this thread from time to time or to schedule it in some way, so your view is only update every second (or whatever you want).
I am studying Java AWT to create GUI applications. I am working on the below code where I cannot make the panel visible inside the frame. Here is my code:
import java.awt.*;
import java.awt.event.*;
/**
*
* #author kiran
*/
public class UserInterface
{
Frame UI;
private static double UIWidth, UIHeight;
/**
* Constructs User Interface
*/
public UserInterface()
{
UI = new Frame("frame");
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
UIWidth = screenSize.getWidth();
UIHeight = screenSize.getHeight();
buildFrame();
buildMessageInputArea();
}
/**
* returns the width of the UI
* #return returns the width of the UI
*/
public static double getUIWidth()
{
return UIWidth;
}
/**
* returns the width of the UI
* #return returns the width of the UI
*/
public static double getUIHeight()
{
return UIHeight;
}
/**
* Builds the frame
*/
private void buildFrame()
{
UI.setSize((int)UIWidth,(int)UIHeight*96/100);
UI.setVisible(true);
UI.setLayout(new FlowLayout());
UI.addWindowListener(new Actions());
}
private void buildMessageInputArea()
{
Panel current = new TextAreaPanel().getPanel();
current.setVisible(true);
UI.add(current);
}
}
class TextAreaPanel extends Frame
{
private Panel textAreaPanel;
TextArea msgInputArea;
public TextAreaPanel()
{
textAreaPanel = new Panel();
msgInputArea = new TextArea(1000,(int)UserInterface.getUIWidth() * 80/100);
}
private void addTextArea()
{
textAreaPanel.add(msgInputArea);
}
public Panel getPanel()
{
return textAreaPanel;
}
}
class Actions extends WindowAdapter
{
#Override
public void windowClosing(WindowEvent c)
{
System.exit(0);
}
}
How can I make the panel visible inside the frame?
How do I make a panel visible inside frame in Java AWT?
There were two fundamental problems with the code as seen, which can be fixed by changing the following:
Add the panel/text area to the GUI before setVisible(true) is called on the top level container.
While it is possible to add components to a container after it has been made visible, they require special handling, and it is not necessary in this case.
Add the text area to the panel!
Here is the code, turned into a Minimal, Complete, and Verifiable example by adding a main(String[]) method, with those two changes implemented, as well as more explanatory comments on other aspects of the code.
import java.awt.*;
import java.awt.event.*;
public class UserInterface {
Frame UI;
private static double UIWidth, UIHeight;
public static void main(String[] args) {
Runnable r = () -> {
new UserInterface();
};
EventQueue.invokeLater(r);
}
/**
* Constructs User Interface
*/
public UserInterface() {
UI = new Frame("frame");
// setting a GUI to full screen while accounting for the task
// bar can be achieved in a single line of code.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
UIWidth = screenSize.getWidth();
UIHeight = screenSize.getHeight();
// these need to be called in the reverse order to ensure the
// components are added before the GUI is set visible.
buildMessageInputArea();
buildFrame();
}
/**
* returns the width of the UI
*
* #return returns the width of the UI
*/
public static double getUIWidth() {
return UIWidth;
}
/**
* returns the width of the UI
*
* #return returns the width of the UI
*/
public static double getUIHeight() {
return UIHeight;
}
/**
* Builds the frame
*/
private void buildFrame() {
UI.setSize((int) UIWidth, (int) UIHeight * 96 / 100);
UI.setVisible(true);
UI.setLayout(new FlowLayout());
UI.addWindowListener(new Actions());
}
private void buildMessageInputArea() {
Panel current = new TextAreaPanel().getPanel();
current.setVisible(true);
UI.add(current);
}
}
// does not need to be a fram
//class TextAreaPanel extends Frame {
class TextAreaPanel {
private Panel textAreaPanel;
TextArea msgInputArea;
public TextAreaPanel() {
textAreaPanel = new Panel();
// these number represent columns and rows, not pixels!
//msgInputArea = new TextArea(1000, (int) UserInterface.getUIWidth() * 80 / 100);
msgInputArea = new TextArea(40, 60);
// add the text area to the panel!
textAreaPanel.add(msgInputArea);
}
/** not called by anything else
private void addTextArea() {
textAreaPanel.add(msgInputArea);
}
**/
public Panel getPanel() {
return textAreaPanel;
}
}
// This can be achieved in a single line of code
class Actions extends WindowAdapter {
#Override
public void windowClosing(WindowEvent c) {
System.exit(0);
}
}
To add to / expand on the comments of #mKorbel & #camickr:
Why use AWT? See this answer for many good reasons to abandon AWT components in favor of Swing.
See Composition over inheritance.
The use of static in GUIs more commonly causes problems, than fixes them. Most (if not all) of the methods marked as static should be reduced to non-static with the code using an instance of the object to call the method.
I recently have implemented clipping in my VTK Java program. I used BoxWidget to control what should be clipped. However, i'm having an issue with vtkRenderWindowInteractor that attached to BoxWidget. The program freezes at the renderWindowInteractor.Start() statement (I've remarked it in my code).
This is my re-simulate code :
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import vtk.*;
public class VTKWindowInteractor extends JPanel {
static {
if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
if (!lib.IsLoaded()) {
System.out.println(lib.GetLibraryName() + " not loaded");
}
}
System.out.println("Make sure the search path is correct: ");
System.out.println(System.getProperty("java.library.path"));
}
vtkNativeLibrary.DisableOutputWindow(null);
}
private vtkPanel renWin;
private vtkRenderWindowInteractor renderWindowInteractor;
private vtkPolyDataMapper mapper;
private vtkActor coneActor;
private vtkPlanes planes;
private vtkBoxWidget boxWidget;
public VTKWindowInteractor() {
setLayout(new BorderLayout());
renWin = new vtkPanel();
add(renWin, BorderLayout.CENTER);
renWin.setMinimumSize(new Dimension(50, 50));
renWin.GetRenderer().SetBackground(0, 0, 0); // black
renWin.GetRenderWindow().AddRenderer(renWin.GetRenderer());
}
public void render() {
mapper = new vtkPolyDataMapper();
vtkConeSource cone = new vtkConeSource();
cone.SetHeight(3.0);
cone.SetRadius(1.0);
cone.SetResolution(10);
mapper.SetInputConnection(cone.GetOutputPort());
coneActor = new vtkActor();
coneActor.SetMapper(mapper);
renWin.GetRenderer().AddActor(coneActor);
planes = new vtkPlanes();
renderWindowInteractor = new vtkRenderWindowInteractor();
renderWindowInteractor.SetRenderWindow(renWin.GetRenderWindow());
boxWidget = new vtkBoxWidget();
boxWidget.SetInteractor(renderWindowInteractor);
boxWidget.SetPlaceFactor(1.25);
boxWidget.PlaceWidget(coneActor.GetBounds());
boxWidget.AddObserver("InteractionEvent", this, "executeClipping");
renderWindowInteractor.Initialize();
boxWidget.On();
renWin.Render();
renWin.resetCamera();
/**************************************/
// This is where the freeze come from //
// //
/************************************/
renderWindowInteractor.Start(); // if i comment out this line, the program works but the boxWidget cannot be resized or rescale or moved
}
public void executeClipping() {
planes = new vtkPlanes();
boxWidget.GetPlanes(planes);
mapper.SetClippingPlanes(planes);
planes.Delete();
}
public static final int WINDOW_WIDTH = 1000;
public static final int WINDOW_HEIGHT = 500;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
VTKWindowInteractor _vtkRendererPanel = new VTKWindowInteractor();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("......");
frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
frame.setVisible(true);
frame.setLayout(new BorderLayout());
frame.add(_vtkRendererPanel);
_vtkRendererPanel.render();
}
});
}
}
I have been finding my mistake for hours and hours and frustrated hence come here to seek for help. If anyone have experienced this or know what did I do wrong please correct me. Thanks !!!
VTK version : 6.2.0
OK. I finally solved the problem. The follows is the quote from vtkPanel.java
/*
*
* Java AWT component that encapsulate vtkRenderWindow, vtkRenderer, vtkCamera,
* vtkLight.
*
* If a vtkInteractor is needed, use vtkCanvas instead. This is necessary when
* Widget and Picker are used.
*
* #author Kitware */
so I changed my
vtkPanel
to
vtkCanvas
&
renderWindowInteractor = new vtkRenderWindowInteractor();
to
renderWindowInteractor = renWin.getRenderWindowInteractor();
and it solves the problem.
Thanks and this is for anyone who are going to face similiar problem as me in the future.
I'm learning Java using Art and Science of Java (using Java SE 6u45). Trying to Change the font of text by entering the new font type in a JTextField. But the problem is that I can't enter any text in JTextField. The problem is common to other swing components i've used like JButton, JCheckBox. But in the latter components I could see the effect of selection, even though the visual selection stays the same, meaning that the check box remains checked even after clicking but the code shows the result of an unchecked box.
But in case of JTextField, not even the effect is showing. Not also could i delete a test text i put in JTextField. Tried to use isEditable() , grabFocus() and isFocusable(). Could it be a Java bug ?
/**
* Example 10.9
*
* This program prints the given text in the font inputted by the user in JTextField
*/
package ASJ_Examples;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JTextField;
import acm.graphics.GLabel;
import acm.program.GraphicsProgram;
public class FontSampler extends GraphicsProgram implements ActionListener{
/**
* Eclispe Generated
*/
private static final long serialVersionUID = -5734136235409079420L;
private static final String TEST_STRING = "This is a test";
private static final double LEFT_MARGIN = 3;
private static final int MAX_FONT_NAME = 10;
public void init(){
addJFontLabel();
addJFontTextField();
lastY = 0;
addGLabel();
}
/**
* Adds a text field to enter the required font
*/
private void addJFontTextField() {
String test = "new";
fontField = new JTextField(test, MAX_FONT_NAME); //added to see if Jtextfiled is responding
// fontField.setEnabled(true);
// fontField.setEditable(true);
fontField.addActionListener(this);
//added these to give focus to jtextfield but no effect
fontField.isEditable();
fontField.grabFocus();
fontField.isFocusable();
//add to window
add(fontField, SOUTH);
}
/**
* Adds JFontLAbel to denote the text input field
*/
private void addJFontLabel() {
add(new JLabel("Font"), SOUTH);
}
/**
* Adds the test label to canvas
*/
private void addGLabel() {
lastLabel = new GLabel(TEST_STRING);
add(lastLabel, 20, 20);
}
public void ActionPerformed(ActionEvent e){
if(e.getSource() == fontField){
GLabel label = new GLabel(TEST_STRING);
label.setFont(lastLabel.getFont()); //to display the text even if the suer entered a non-allowed font
label.setFont(fontField.getText()); //change the font to u4ser demanded font
addGlabel(label);
lastLabel = label;
}
}
/**
*adds a Glabel on the next line adjusting for heights
* #param label
*/
private void addGlabel(GLabel label) {
lastY += label.getHeight();
lastY += lastLabel.getDescent() - label.getDescent();
add(label, LEFT_MARGIN, lastY);
}
/**
* JTextField to enter font
*/
private JTextField fontField;
/**
* GLabel which is being worked on
*/
private GLabel lastLabel;
/**
*
*/
private double lastY;
}
try using fontField.requestFocus(); instead of fontField.grabFocus();
and fontField.setEditable(true); instead of fontField.isEditable();
fontField.setFocusable(true); instead of fontField.isFocusable();
btw fontField.setEditable(true); and fontField.setFocusable(true); are not necessary by default they are set to true.
As #andrew-thompson pointed out, the issue was mix of awt and swing. I suppose somehow the GComponent was overlaying Swing component JTextField which made it inaccessible. So the workaround is to create JPanel and a KeyListener to the JTextField as noted by #marco .
This is the code that works :
SSCCE Code
/**
*
* This program prints the given text in the font inputted by the user in JTextField
*/
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.JTextField;
import acm.graphics.GLabel;
import acm.program.GraphicsProgram;
public class FontSampler extends GraphicsProgram implements KeyListener{
private static final String TEST_STRING = "This is a test";
private static final double LEFT_MARGIN = 3;
private static final int MAX_FONT_NAME = 10;
public void init(){
initPanel(); //init panel
addJFontTextField(); //adds fontField to enter the font type
addGLabel(); //adds default label to GCanvas
lastY = 0; //default y offset for post-processed label
add(panel); //adds panel to canvas
}
/**
* initialises panel
*/
private void initPanel() {
panel = new JPanel();
panel.setLayout(new BorderLayout());
}
/**
* Adds a text field to enter the required font
*/
private void addJFontTextField() {
fontField = new JTextField( MAX_FONT_NAME);//added to see if Jtextfiled is responding
panel.add(fontField, BorderLayout.SOUTH);
fontField.addKeyListener(this); //adds key listener
}
/**
* Adds the test label to canvas
*/
private void addGLabel() {
lastLabel = new GLabel(TEST_STRING);
add(lastLabel, 20, 20);
}
/**
* Called when any key is pressed
*/
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ENTER){//check for enter key pressed
GLabel label = new GLabel(TEST_STRING);
label.setFont(lastLabel.getFont());
label.setFont(fontField.getText());
addGlabel(label);
lastLabel = label;
}
}
/**
*adds a Glabel on the next line adjusting for heights
* #param label
*/
private void addGlabel(GLabel label) {
lastY += label.getHeight();
lastY += lastLabel.getDescent() - label.getDescent();
add(label, LEFT_MARGIN, lastY);
}
/**
* JTextField to enter font
*/
private JTextField fontField;
/**
* GLabel which is being worked on
*/
private GLabel lastLabel;
/**
*
*/
private double lastY;
private JPanel panel;
}
Thanks :)
But in the latter components I could see the effect of selection, even though the visual selection stays the same, meaning that the check box remains checked even after clicking but the code shows the result of an unchecked box.
That sounds very strange. Maybe the GraphicsProgram class is doing something naughty. Cannot tell w/o its code though.
fontField.isEditable();
fontField.grabFocus();
fontField.isFocusable();
The first returns a boolean if the field is editable (it is by default).
The second should not be used by client programs, use fontField.requestFocusInWindow() instead. The third returns a boolean if the field is focusable (it is by default).
fontField.addActionListener(this);
An ActionListener on a JTextField does nothing. Try doing this:
fontfield.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void removeUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void insertUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void changedUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
}
});
I am currently making a Twitter client, and I found some issue I couldn't solve myself.
I'm not sure what part of the code should I include, so I'll post a picture.
Picture
I have a JPanel in a JScrollPane, and then I add small JPanels (the tweets) to that JPanel. But there's always a space after those components.
Any advice about where is that space came from?
Thank You in advance.
Here are some pieces of code:
This is the main JPanel, that handles the Tweet JPanels:
package net.rothens.twitt3ns.gui;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.*;
import net.rothens.twitt3ns.Twitt3ns;
import twitter4j.Status;
/**
*
* #author Rothens
*/
public class TweetsPanel extends JPanel {
public java.util.List<Long> timestamps;
public TweetsPanel() {
initUI();
}
public final void initUI() {
timestamps = new ArrayList<Long>();
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
}
public void addTwitt(Status s) {
if (!Twitt3ns.tw.mw.isScrollbarOnTop()) {
Twitt3ns.tw.mw.saveScrollbarPosition();
}
int pos = getPos(s.getCreatedAt().getTime()) + 1;
TweetPanel tp = new TweetPanel(s);
if (pos >= getComponentCount()) {
add(tp);
} else {
add(tp, pos);
}
validate();
if (!Twitt3ns.tw.mw.isScrollbarOnTop()) {
Twitt3ns.tw.mw.loadScrollbarPosition(tp.getHeight());
}
}
/**
* Update the time on the panels
*/
public void updatePanels() {
for (Component c : getComponents()) {
if (c instanceof TweetPanel) {
((TweetPanel) c).updateTime();
}
}
validate();
}
/**
* Gets the position of a new tweet
* #param what the time when the new component was created
* #return position of the new component
*/
public int getPos(long what) {
timestamps.add(what);
Collections.sort(timestamps);
return timestamps.size() - timestamps.indexOf(what) - 2;
}
public TweetsPanel(int id) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TweetsPanel tl = new TweetsPanel();
tl.setVisible(true);
}
});
}
}
The Tweet JPanels code is this (I'll post in pastebin, it's way too big) : Pastebin
And in the Main JFrame, I create the tabbed pane, and the ScrollPanes in this way:
tabPane.setTabPlacement(javax.swing.JTabbedPane.BOTTOM);
tabPane.setAlignmentX(0.0F);
tabPane.setAlignmentY(0.0F);
spHome.setAlignmentX(0.0F);
spHome.setAlignmentY(0.0F);
spHome.setHorizontalScrollBar(null);
tabPane.addTab("Otthon", spHome);
tabPane.addTab("#", null, spMention, "Tweetek amik Téged említenek");
And this is how I add the JPanels to the JScrollPanes:
tpHome.setBorder(null);
tpHome.setFocusable(false);
spHome.setViewportView(tpHome);
tpMention.setBorder(null);
tpMention.setFocusable(false);
spMention.setViewportView(tpMention);