Updating the edge weight displayed without being "cluncky" - java

I am using Jgrapht to build a simulation environment based on a directed weighted graph. I now want to display the simulation using Jgraph.
While I have figured out how to display the graph and update it as the simulation runs, I have noticed that when the edge weights update, the entire window flickers. Presently I an calling frame.paintComponents() to update the window.
I believe that I can get it to only update the individual edges that are changing, but I am not familiar with java.awt.
public static void main(String [] args) throws InterruptedException
{
Simulation newSim = new Simulation(31, .01);//extends ListenableDirectedWeightedGraph
SimulationViewer applet = new SimulationViewer(newSim);//extends JApplet
applet.init();
JFrame frame = new JFrame();
frame.getContentPane().add(applet);
frame.setTitle("Simulation Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
//run simulation
for (;newSim.getStep() < newSim.getMAX_STEP(); newSim.incrementStep()) {
BreadthFirstIterator<SimulationBlock, Signal> iter =
new BreadthFirstIterator<SimulationBlock, Signal>(newSim, newSim.head);
while (iter.hasNext()) {
iter.next().execute(newSim);
//update graphics
frame.paintComponents(applet.getGraphics());//looks clunky
Thread.sleep(500);
}
}
}

Looks like I needed to call the update method for applet. Replaced:
frame.paintComponents(applet.getGraphics());//looks clunky
With:
applet.update(applet.getGraphics());
This looks a little funky and maybe I need to refactor this code so that is within the SimulationViewer class.

Related

Can you make a JPanel randomly generate each time a button is clicked?

Basically just started coding in Java using Eclipse and as my first "serious" project I'm trying to code a simple quiz game. I already set up all the graphics and the answering system but I'm getting stuck at the part where, if you click the right answer, the JPanel restarts with a new question.
I already tried some solutions I've seen online including a do/while method, which proved worthless and calling the main method ( the one where all the code is) which seems impossible.
Here's the method I'm talking about:
public static void main(String []args) throws IOException
{
//here was unnecessary stuff i cut out
ImageIcon image = new ImageIcon (Imagetesting.class.getResource(i+".jpg"));
JLabel label = new JLabel (image);
JFrame f = new JFrame("Quiz");
JLabel x1 = new JLabel(question);
JButton x2 = new JButton(answer1);
//+ other graphic stuff
f.getContentPane().add(MyPanel, "Center"); // Paste MyPanel in center
// of the contentPane
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
f.setVisible(true);
x3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(answer2.equals("therightanswer")){
score = score +1;
x1.setText("Right answer Punteggio:"+String.valueOf(punteggio)
// what am I supposed to put here?
);
;
}
}});
So what am I supposed to do? Is it even possible to call the main method to make it restart? Am I doing something wrong?
You can pass the labels into the actionPerformed function to change the values of those objects when the answer is correct.

How to modify a graph appearance in JUNG

I'm trying to visualize a tree graph with the JUNG library.
The code I use is:
JPanel base = new JPanel();
Graph<String, String> grafo = OntologyGraph.getGraph(ontology);
Layout<String, String> layout = new TreeLayout<String, String>((Forest<String, String>) grafo);
VisualizationViewer<String, String> vv = new VisualizationViewer<String, String>(layout);
vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<String>());
vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller<String>());
vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
final DefaultModalGraphMouse<String, Number> graphMouse3 = new DefaultModalGraphMouse<>();
vv.setGraphMouse(graphMouse3);
graphMouse3.setMode(DefaultModalGraphMouse.Mode.PICKING);
base.add(vv);
return base;
It displays this
Now I want to change the circled verteces with a labelled JButton and to enlarge the space between them, but I can't find a tutorial on the web to achive this.
Changing the spacing between the nodes is easy enough; just use the TreeLayout constructor that accepts the distx and disty parameters.
Providing a JButton for each node is not something that JUNG natively supports, although you could do some hacking to enable it.
What problem are you trying to solve by using JButtons for nodes?
Here is some example code that you can use to open a JFrame with information about the node that was clicked (when you are in picking mode). If you want to have it respond to node clicks even when you are in the transforming mode, you'd have to change the graphmouseplugins a little to not remove the PickingGraphMousePlugin when in transforming mode.
vv.getRenderContext().getPickedVertexState().addItemListener(new ItemListener(){
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
JFrame frame = new JFrame("Vertex "+e.getItem()+" picked");
frame.getContentPane().add(new JButton("hello from "+e.getItem()));
frame.setSize(new Dimension(200,100));
frame.setLocation(200, 200);
frame.setVisible(true);
}
}
});
If you want the vertices to look more like rectangular buttons, the VertexLableAsShapeDemo may help. That demo uses JLabels to draw the vertices

How do I resize and dispose my JFrame window?

So I'm taking my first course Java and I'm stumped on my final project. I had to create the game Sokoban from the ground up given a levelReader from my prof. Now my entire game works correctly; tiles are painted, player and boxes move correctly, etc.
However, I have two issues that are minor. These can practically be ignored for final submission but I want to figure this out so I have a more solid understanding.
So my two issues are
a) after the last level is completed (level == totalLevels where level 1 is index 0) the window is disposed and
b) I want every new level generated by initLevel to resize the window.
public void initLevel(int level) {
if(level == totalLevels) { this.dispose(); } //incorrect, unsure what to use
/*
.
. BODY
.
*/
this.setPreferredSize(new Dimension(50*currentLevel.length, 50*currentLevel[0].length));
//sets the window size initially but succeeding levels don't resize
repaint();
}
public static void main(String args[]) {
JFrame f = new JFrame("Sokoban");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLayout(new FlowLayout());
f.add(new Sokoban("levels.txt"));
f.pack();
f.setVisible(true);
}
Unrelated code was removed from both classes.

Formatting a JGraph graph using com.jgraph.layout - refreshing the display

I'm writing my very first program in Java that actually does UI, so please bear with me if the answer to this is obvious.
I'm using JGraph 5 (5.14) to visualize a graph created by JGrapht (0.8.3).
I can create the graph with JGrapht just fine, and I believe it gets converted to JGraph OK using org.jgrapht.ext.JGraphModelAdapter. The problem is, when the result is displayed in a window (I'm using a panel in a JApplet) all the vertices are displayed on top of another.
Someone else had this problem (JGraph Layout Does Not Work) and I tried the solution presented there, but then only two nodes are displayed. Basically, I just want the graph displayed in some way where the nodes are separate from each other.
Some code is worth a thousand words, so here is what I currently have, which only displays two nodes (there are 219 in the graph):
class ourGraphVisualizer extends JApplet
{
private static final Color DEFAULT_BG_COLOR = Color.decode("#FAFBFF");
private static final Dimension DEFAULT_SIZE = new Dimension(1280, 1024);
// this init overrides the JApplet.init(). Our class here extends JApplet so we can do the visualization
public void init(ListenableDirectedWeightedGraph<String, DefaultWeightedEdge> theGraph)
{
JGraphModelAdapter<String, DefaultWeightedEdge> jgAdapter;
JPanel panel = new JPanel();
panel.setPreferredSize(DEFAULT_SIZE);
JScrollPane scrollpane = new JScrollPane(panel);
scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
this.getContentPane().add(scrollpane, BorderLayout.CENTER);
JFrame frame = new JFrame();
frame.add(this);
frame.setTitle("Call Graph, " + theGraph.vertexSet().size() + "nodes");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setPreferredSize(DEFAULT_SIZE);
jgAdapter = new JGraphModelAdapter<String, DefaultWeightedEdge>(theGraph);
JGraph jgraph = new JGraph(jgAdapter);
panel.add(jgraph);
resize(DEFAULT_SIZE);
// Let's see if we can lay it out
JGraphFacade jgf = new JGraphFacade(jgraph);
JGraphFastOrganicLayout layoutifier = new JGraphFastOrganicLayout();
layoutifier.run(jgf);
System.out.println("Layout complete");
final Map nestedMap = jgf.createNestedMap(true, true);
jgraph.getGraphLayoutCache().edit(nestedMap);
jgraph.getGraphLayoutCache().update();
jgraph.refresh();
frame.setVisible(true);
panel.setVisible(true);
scrollpane.setVisible(true);
}
Any constructive suggestions/help/inspiration will be greatly appreciated!
Thanks...
-Eric
If u want to avoid overlapping of your Vertex just try different graph Layout i havegiven some here this one for hierarchical layout and call run method of this
final JGraphHierarchicalLayout hir = new JGraphHierarchicalLayout();
final JGraphFacade graphFacade = new JGraphFacade(jgraph);
hir.run(graphFacade);
final Map nestedMap = graphFacade.createNestedMap(true, true);
jgraph.getGraphLayoutCache().edit(nestedMap);
It'll be a much better idea to create two JPanels and add your graphs individually to the JPanels and the JPanels to the the JFrame using an appropriate layout manager

JPanels, JFrames, and Windows, Oh my!

Simply stated, I am trying to make a game I am working on full-screen.
I have the following code I am trying to use:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
if(!gs.isFullScreenSupported()) {
System.out.println("full-screen not supported");
}
Frame frame = new Frame(gs.getDefaultConfiguration());
Window win = new Window(frame);
try {
// Enter full-screen mode
gs.setFullScreenWindow(win);
win.validate();
}
Problem with this is that I am working within a class that extends JPanel, and while I have a variable of type Frame, I have none of type Window within the class.
My understanding of JPanel is that it is a Window of sorts, but I cannot pass 'this' into gs.setFullScreenWindow(Window win)... How should I go about doing this?
Is there any easy way of calling that, or a similar method, using a JPanel?
Is there a way I can get something of type Window from my JPanel?
-
EDIT: The following method changes the state of JFrame and is called every 10ms:
public void paintScreen()
{
Graphics g;
try{
g = this.getGraphics(); //get Panel's graphic context
if(g == null)
{
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(frame.getExtendedState()|JFrame.MAXIMIZED_BOTH);
frame.add(this);
frame.pack();
frame.setResizable(false);
frame.setTitle("Game Window");
frame.setVisible(true);
}
if((g != null) && (dbImage != null))
{
g.drawImage(dbImage, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync(); //sync the display on some systems
g.dispose();
}
catch (Exception e)
{
if(blockError)
{
blockError = false;
}
else
{
System.out.println("Graphics context error: " + e);
}
}
}
I anticipate that there may be a few redundancies or unnecessary calls after the if(g==null) statement (all the frame.somethingOrOther()s), any cleanup advice would be appreciated...
Also, the block error is what it seems. I am ignoring an error. The error only occurs once, and this works fine when setup to ignore the first instance of the error... For anyone interested I can post additional info there if anyone wants to see if that block can be removed, but i'm not concerned... I might look into it later.
Have you made any progress on this problem? It might be helpful if you could update your question with your expected behavior and what the code is actually doing? As was already pointed out, JFrame is a subclass of Window, so if you have a JFrame, you don't need a Window.
For what it's worth, I have a Java app which works in fullscreen mode. Although the screen is not repainted as often as yours, it is repainted regularly. I do the following to enter fullscreen:
// pseudo-code; not compilable
JPanel container = new JPanel();
container.setOpaque( true ); // make sure the container will be visible
JFrame frame = new JFrame();
frame.getContentPane().add(container); // add the container to the frame
frame. ... //other initialization stuff, like default close operation, maximize, etc
if ( fullScreenModeIsSupported )
frame.setUndecorated( true ); // remove window decorations from the frame
gs.setFullScreenWindow( frame );
frame.validate();
Then whenever I need to update the screen, I just plug a new JPanel into the container JPanel:
// pseudo-code; not compilable
container.removeAll(); // clean out the container
container.add( jPanelWithNewDisplay ); // add the new display components to the container
container.validate(); // update and redisplay
container.repaint();
Can't claim that it's technically perfect, but it works well for me. If the pseudo-code examples don't cut it, I can spend some time putting together a compilable example.
JPanel is not a subclass of Window. JFrame is.
So you could try:
JFrame yourFrame = new JFrame();
yourFrame.add(yourPanel);
appyYourFullScreenCodeFor( yourFrame );
That should work.
I think I got what you need.
Set the frame undecorated, so it
comes without any title bar and
stuff.
Add your panel to the frame., so it
looks like only your panel is shown.
Maximize your frame. So now it
should look like there's only your
panel taking the full screen without
and window stuff.
frame.setUndecorated(true);
frame.add(panel); //now maximize your
frame.
Note: Its important to note that the undecorated API can only be called when your frame is undisplayable, so if its already show, then first you need to do setVisible(false).
EDIT1: If all you want is to get the window containing your panel, then you can do this:
Window win = SwingUtilities.getAncestorOfClass(Window.class, myPanel);
Once you get the window instance you can pass it wherever you want.
EDIT2: Also the Frame class extends Window so you can directly do gs.setFullScreen(frame). You dont need to create a new window for that frame.
My understanding of JPanel is that it
is a Window of sorts
Why would you think that? Did you read the API? Does JPanel extend from Window?
You can try using the SwingUtilities class. It has a method that returns the Window for a given component.

Categories

Resources