I've tried a lot of things but I still cannot figure it out. I have a List that contains "entities". I'm going trought all of these and rendering them. This works perfectly fine. The problem is that when I remove one object (entity) in this List from different thread. In this case the square (entity) won't disappear until I resize the window.
private List<Entity> entities = new ArrayList<Entity>();
public void render(Graphics g, ImageObserver obs) { //This function is called from my game loop (few hundred times per second..)
for (int i = 0; i < entities.size(); i++) {
entities.get(i).render(); //Calling the render function in the entity class
}
}
public void removeEntity(int index) { //This function is called from different thread
entities.remove(index); //Removing entity from the list
}
Your render() function is not being called. You need to call repaint() to do this. This will call render() and update the JFrame. Resizing the window repaints the window automatically, which is why it worked only after you resized it.
Related
I'm using GraphStream to show a map of an area and I've tried to inherit from the default MouseManager DefaultMouseManager and to override the mouseClicked method so that when clicking on a node the following will happened:
node's color will change.
node's label will show.
node's data will show in terminal.
I do know that the method works because the node's data does get printed to terminal, but I think some other mouse event repaint the node and rehide the label so they doesn't change when clicking on a node.
here is my MouseManager's code:
public class CustomMouseManager2 extends DefaultMouseManager {
protected View view;
protected GraphicGraph graph;
private GraphicElement focusedNode;
#Override
public void init(GraphicGraph graph, View view) {
super.init(graph, view);
.
.
.
}
#Override
public void mouseClicked(MouseEvent e) {
GraphicElement currentNode = view.findNodeOrSpriteAt(e.getX(), e.getY());
if(currentNode != null){
OGraph graph = OGraph.getInstance();
Random r = new Random();
currentNode.setAttribute("ui.style", "fill-color: red; text-mode: normal;");
ONode oNode = graph.getNode(Long.parseLong(currentNode.getLabel()));
System.out.println(oNode.toString());
}
if(focusedNode!= null)
focusedNode.setAttribute("ui.style", "fill-color: black;size: 10px, 10px; text-mode: hidden;");
focusedNode = currentNode;
}
}
I've tried to check what methods from the base class DefaultMouseManager are called after my mouseClicked is called so I could override them too, but there was to many of them to follow.
Is there an elegant way to make sure my changes will execute after all other method from the base class?
Is there an elegant way to make sure my changes will execute after all other method from the base class?
Read the documentation and look at the code in DefaultMouseManager. I googled DefaultMouseManager, looked at the documentation, went through the inheritance of the different interfaces until I got to MouseListener, which describes the order of operations. Then I looked at mouseClicked and mouseReleased since they would be called last, mouseClicked is empty so that leaves mouseReleased and the methods that are called in it.
So, something similar to this question has happened, the mouseClicked() method was called twice.
In my code, I repaint black the previous node and hide its label after a new node is clicked. And for that reason, when the mouseClicked() method was called twice then the first call changed the node`s appearance and the second one changed it back.
In that case, an easy fix will be to check if the previous node and current node are the same. replace this if(focusedNode!= null) with this
if(focusedNode!= null && focusedNode != currentNode)
but a more straightforward solution will be to understand why the method is been called twice.
My guess is that it has something to do with the inheritance but I'm not sure.
In general, my goal is to draw lines defined by the user's cursor. To accomplish this, I am figuring out the calculations for those lines in one class, and then updating the class that paints the lines with those new values. Overall I want to access a list of line segments, a list of nodes, and the current abstract "node" that the cursor is located at. (Nodes and Line Segments are my own defined classes). The class in which the lines are drawn is called GraphicsPanel.
I set up access between the classes as follows:
public class MainClass extends JFrame {
protected static ArrayList<LineSegment> lineList = new ArrayList<LineSegment>();
protected static ArrayList<Node> nodeList = new ArrayList<Node>();
protected static Node current = new Node();
// Code for calculations and user interactions
{
GraphicsPanel displayPanel = new GraphicsPanel();
// Values are updated
displayPanel.revalidate();
displayPanel.repaint();
}
}
public class GraphicsPanel extends JPanel {
private ArrayList<LineSegment> lineList = package.MainClass. lineList;
private ArrayList<Node> nodeList = package.MainClass.nodeList;
private Node current = package.MainClass.current;
public GraphicsPanel() {
}
public void paint(Graphics g) {
// Paint lines and other shapes
}
}
While the lineList and nodeList objects get correctly updated when a new LineSegment or Node is added to the list, the current Node is never updated and always shows the default of (0, 0).
As an example, within the main class, I have two mouse listeners, one for mouse clicks and one for mouse movement. They have similar functions, but the mouse click listener updates both the current Node and the lineList ArrayList of LineSegments.
displayPanel.addMouseListener(new MouseListener() {
#Override
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
current = new Node(p.getX(), p.getY());
lineList.add(new LineSegment(current, current);
// Don't worry, the line segment gets updated (correctly) with a new end node as
// the cursor moves around the window
displayPanel.revalidate();
displayPanel.repaint();
}
});
When I click on the window to create lines, the lines show up as expected but the current Node remains at (0, 0). I am completely flabbergasted by this, since it seems like only one of the variables is updating, even though both are written to update in basically the same way: I modify the instance of the class variable in the main class, which should modify the instance of the variable in the GraphicsPanel class.
I appreciate any help with this conundrum and welcome suggestions for what's wrong, as well as better ways to approach this application.
You don't modify the instance, you create a new instance, replacing the old. This means that GraphicsPanel.current will keep pointing to the original instance, but MainClass.current will point to a new distance.
If you did something like instance.setY(p.getY()), it would modify the single original instance that both classes are pointing to.
Your MouseListener adds objects to the Main class list.
Then it assigns a different new object to the panel reference current. But that doesn't change the Main class refence!
You could just not have another current reference in the panel code. Simply directly assign to the current instance that belongs to the Main class!
all:
I have created a PetCanvas class to handle an ArrayList of pets that each have their own draw method. This draw method is void and accepts a GraphicsContext object that is used to specify how the pet is drawn. The GraphicsContext object comes from the PetCanvas class that has a void method sketchPet that calls draw on each of the pets in the list. I want to use the PetCanvas object to draw the Graphics to the GUI but the compiler will not allow me to add PetCanvas.sketchPet to the root because sketchPet does not return a Node object. Any suggestions? Or any more information needed to determine a solution?
Thank you in advance.
I'm beginning to think the issue lies here:
public void sketchPets() {
if (this.drawableList.size() == 0) {
throw new IllegalArgumentException("The list has no animals to draw");
}
for (Drawable current : this.drawableList) {
current.draw(this.getGraphicsContext2D());
}
}
The current.draw line does nothing with the GraphicsContext object after it is drawn. I'm not sure how to remedy this issue if it is the cause.
Actually, I have a JFrame(the main window) with a JTable in it. And couple of buttons, like Add,Delete,Refresh.
Refresh uses the function(updateTable) that has the following code below and works fine:
try
{
ResultSet R = Home.getStatement().executeQuery("Select * from Schooldata");
int count =0;
while(R.next()) { count++; }
school_data = new String[count][6];
R = Home.getStatement().executeQuery("Select Schoolname,city,ProgramOpted,coordinator_name,Trainers,contactnum from Schooldata");
count =0;
while(R.next())
{
for(int i=0;i<6;i++)
{ school_data[count][i]= R.getString(i+1);
System.out.println(R.getString(i+1));
}
count++;
}
}
catch(SQLException S) {JOptionPane.showMessageDialog(null,S);}
jTable1.setModel(new DefaultTableModel(school_data,new String [] {
"School Name", "City", "Program", "Coordinator", "Trainers", "Contact Number"
}));
When I click on "Add, another JFrame window appears and asks for Details that is further saved to Database and shows a confirmation message and refreshes the table(on a different JFrame i.e the main Window) using above function.
The Issue is, I'm calling the same function but from an another JFrame.Expecting the changes to be reflected in the main JFrame.
Using the method,new Main().updateTable(); in the below code.It's just not working.
try
{
int confirm = Home.getStatement().executeUpdate(Query);
if(confirm == 1)
{
JOptionPane.showMessageDialog(null,"Record Added","Saved",1);
new Main().updateTable();
}
else JOptionPane.showMessageDialog(null,"There is some Error.....","Error",0);
}
catch(SQLException S)
{
JOptionPane.showMessageDialog(null,S,"Error",0);
}
Your problem I believe is here (it's hard to tell without a minimal example program:
int confirm = Home.getStatement().executeUpdate(Query);
if(confirm == 1)
{
JOptionPane.showMessageDialog(null,"Record Added","Saved",1);
new Main().updateTable(); // ****** HERE ******
}
You're creating a completely new Main object, changing its state, and hoping that this will change the state of the visualized Main object, but you're finding out that no, it won't.
Instead you need to pass a reference of the visualized Main object into the code above, and then call methods on it, not on a newly created completely unique object.
Whatever you do, don't try solving this by making fields or methods static. Yes, that might work, but it breaks OOPs and makes your program difficult to test or extend.
As an aside, that second dependent window should not be another JFrame, and in fact likely should be a modal JDialog. For if you use a JDialog, then there would be no need for the dialog code to push information into the calling window. Rather the calling code will know when you're done dealing with the dialog, and so at this point if the dialog's state is good (if you didn't say cancel it with no changes), then the calling code can easily pull information from the dialog code. For a concrete example of what I"m talking about, please look at my answer to a similar question about passing information between two windows here.
Also a similar problem and solution can be found here.
See weather you are disposing the main or not. If not then try creating object of Main frame and try accessing it to refresh table. You can also add import for Main Frame .java file in your refresh dialog file and try refreshing the table. Also check if your table is public static or not so that to access it from another frame. If you create a refresh function for this purpose then it will be best. My code for function goes as -
import package.mainframe;
or
MainFrame mainframe = new MainFrame();
try
{
int confirm = Home.getStatement().executeUpdate(Query);
if(confirm == 1)
{
JOptionPane.showMessageDialog(null,"Record Added","Saved",1);
mainframe.updateTable(); //or mainframe.functioncall();
}
else JOptionPane.showMessageDialog(null,"There is some Error.....","Error",0);
}
catch(SQLException S)
{
JOptionPane.showMessageDialog(null,S,"Error",0);
}
I'm trying to create in-game window, using Table class. But when i added groups of images to that table, seems row() method has no influence to groups, they all are in the same place. Using Images instead of Groups works.
PS. I used Group to overlap images (kinda border for hover effect), don't know better way to do that.
Thanks
public class MyGroup extends Group{
public MyGroup(Image bg, Image thumb){
this.addActor(bg);
this.addActor(thumb);
}
}
public class ActionScreen extends Table {
MyGroup[] group =new MyGroup[8];
for (int i=0;i<8;i++){
group[i] = new MyGroup(new Image(skin.getDrawable("item-bg")),new Image(skin.getDrawable("item-bg-over")));
if (i==4){
row();
add(group[i]).top().padLeft(100);
}
else{
add(group[i]).top().padLeft(100);
}
}
Group's, by default, have zero size, so you have to manually set the size.
In your MyGroup constructor, you'd want to call something like this
this.setSize(bg.getWidth(), bg.getHeight());