VtkRenderWindowInteractor doesn't start and cause program freezes [java] - java

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.

Related

Java Actionlistener changes class variable but Main file doesn't see it if while loop is empty [duplicate]

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

Inheritance, Static, and confusion

I have 3 Java books, and use online resources, including the posts on this website, also but something is just not clicking. New too programming in general and not the brightest bulb so please try and dumb down the responses if at all possible. Going to try and explain in detail the best I can, sorry if this is a long post and THANK YOU FOR YOUR TIME. Also, am using IntelliJ IDEA IDE
GOAL:
I'm trying to create a simple "Game" that implements a GUI, you click 1 of 3 JButtons to perform an action, and above the JButtons is a JTextArea used to relay all the information to the User.
PROBLEM: I'm not referencing objects in other classes correctly and creating static methods and variables to compensate (I think) But please take a look and let me know what else I'm doing incorrectly I need comments and criticism from people that know whats up.
SIDE NOTE:
Its buggy and a lot has been turned into a "static" method or variables in order to use between classes. When it came time to create a new "Level" I couldn't recycle my enemy ArrayList and load new enemies in it due to the static nature of it all. I will post the working version but I have started to rebuild it for practice makes perfect, and possibly upgrade my code.
As far as structure, should each "Level" be its own class, should all the levels be in an ArrayList like the enemies, and should I have 1 class that works as the game loop?
Is there a generic best way when creating something or as long as it works it doesn't matter? (opinions please)
I have 6 Packages and 13 Classes which is a lot of code, so I will just print the classes I believe are of importance to the situation.
Main Class:
package Primary;
import GUI.PrimaryFrame;
import Game.Loop;
/**
* Created by Thunderfoot on 8/4/2016. Keep Growing!
*/
public class Alpha {
public static void main(String[] args) {
//Instantiate our GUI
PrimaryFrame frameGUI = new PrimaryFrame();
frameGUI.buildGUI();
//Instantiate our game loop
Loop.newGame();
}
}
GUI:
package GUI;
import javax.swing.*;
import java.awt.*;
/**
* Graphical User Interface requires:
* 1 JFrame (PrimaryFrame)
* 4 JPanel (outputPanel, characterStatsPanel, topButtonPanel, bottomButtonPanel)
* 3 JTextArea (output, playerStats, enemyStats)
* 1 JScrollPane (output)
* 3 JButton (attackButton, kickButton, powAttButton)
*/
public class PrimaryFrame extends JFrame {
private OutputPanel outPanel = new OutputPanel();
private StatsPanel statPanel = new StatsPanel();
private TopButtons topPanel = new TopButtons();
private BottomButtons botPanel = new BottomButtons();
//Constructor
public PrimaryFrame() {
//frame
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
Dimension FRAME_MIN = new Dimension(400, 600);
setMinimumSize(FRAME_MIN);
Dimension FRAME_MAX = new Dimension(600, 800);
setMaximumSize(FRAME_MAX);
setTitle("Generic Fighting Game");
getContentPane().setBackground(Color.BLACK);
}
public void buildGUI() {
//Add components and spacing
add(Box.createRigidArea(new Dimension(8, 8)));
add(outPanel);
add(Box.createRigidArea(new Dimension(8, 8)));
add(statPanel);
add(Box.createRigidArea(new Dimension(8, 8)));
add(topPanel);
add(Box.createRigidArea(new Dimension(8, 8)));
add(botPanel);
add(Box.createRigidArea(new Dimension(8, 8)));
//Set attributes
pack();
setLocationRelativeTo(null);
setVisible(true);
}
}
Output Panel:
package GUI;
import javax.swing.*;
import javax.swing.text.DefaultCaret;
import java.awt.*;
/**
* Created by Thunderfoot on 8/4/2016. Keep Growing!
*/
public class OutputPanel extends JPanel {
//Class variables
public static JTextArea output;
OutputPanel() {
Font myFont = new Font("Serif", Font.BOLD, 16);
BoxLayout outFlow = new BoxLayout(this, BoxLayout.X_AXIS);
setLayout(outFlow);
setBackground(Color.GRAY);
setMinimumSize(new Dimension(400, 100));
setMaximumSize(new Dimension(600, 300));
//TextArea
output = new JTextArea(1,50);
output.setLineWrap(true);
output.setWrapStyleWord(true);
output.setEditable(false);
output.setFont(myFont);
JScrollPane outputScroll = new JScrollPane(output, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
outputScroll.isWheelScrollingEnabled();
//TextArea always scroll to bottom after update
DefaultCaret caret = (DefaultCaret)output.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
//Add components and spacing
add(Box.createRigidArea(new Dimension(8, 8)));
add(outputScroll, CENTER_ALIGNMENT);
add(Box.createRigidArea(new Dimension(8, 8)));
}
}
Game Loop:
package Game;
import Characters.BasicEnemy;
import Characters.UserCharacter;
import GUI.BottomButtons;
import GUI.TopButtons;
import Levels.Level_One;
import Levels.Tutorial;
import java.util.ArrayList;
public class Loop {
//Class variables
public static UserCharacter player;
public static ArrayList<BasicEnemy> enemyList;
public static int currLevel = 0;
public static void newGame() {
combatDisabled();
switch (currLevel) {
case 0:
Tutorial tutorial = new Tutorial();
tutorial.runTutorial();
combatEnabled();
break;
case 1:
Level_One lvl1 = new Level_One();
lvl1.runLevelOne();
combatEnabled();
break;
}
}
public static void combatEnabled() {
TopButtons.attackButton.setEnabled(true);
TopButtons.kickButton.setEnabled(true);
}
public static void combatDisabled() {
TopButtons.attackButton.setEnabled(false);
TopButtons.kickButton.setEnabled(false);
BottomButtons.powAttButton.setEnabled(false);
}
}
Level 1:
package Levels;
import Characters.BasicEnemy;
import Characters.UserCharacter;
import CombatSystem.Combat;
import GUI.OutputPanel;
import Game.Loop;
import java.util.ArrayList;
public class Tutorial {
public void runTutorial() {
//Instance variables
Loop.player = new UserCharacter(100, 10);
BasicEnemy enemy0 = new BasicEnemy(100, 5);
BasicEnemy enemy1 = new BasicEnemy(100, 5);
BasicEnemy enemy2 = new BasicEnemy(100, 5);
Loop.enemyList = new ArrayList<>();
Loop.enemyList.add(enemy0);
Loop.enemyList.add(enemy1);
Loop.enemyList.add(enemy2);
OutputPanel.output.append("Greetings player! Use the buttons at the bottom of the screen to fight your opponent.");
Combat.statusUpdate();
Loop.combatEnabled();
}
}
Class that handles combat:
package CombatSystem;
import GUI.BottomButtons;
import GUI.OutputPanel;
import GUI.StatsPanel;
import Game.Loop;
import java.util.Random;
public class Combat {
//Player stats
private static int playerCurrHealth = Loop.player.getHealth();
private static int playerCurrRage = Loop.player.getRageMeter();
private static int playerAttack = Loop.player.getAttackPower();
private static int playerKick = Loop.player.getKickPower();
private static int playerPowAttack = Loop.player.getRagePower();
//Enemy stats
private static int enemyCurrHealth = Loop.enemyList.get(0).getHealth();
private static int enemyCurrRage = Loop.enemyList.get(0).getRageMeter();
private static int enemyAttack = Loop.enemyList.get(0).getAttackPower();
//Fighting
private static boolean fighting = true;
public Combat() {
}
//Update status fields
public static void statusUpdate() {
StatsPanel.playerStats.setText(" <" + playerCurrHealth + "> [" + playerCurrRage + "] ");
StatsPanel.enemyStats.setText(" <" + enemyCurrHealth + "> [" + enemyCurrRage + "] ");
}
//Basic attack
public static void basicAttack() {
if (fighting) {
playerBasicAttack();
if (enemyCurrHealth <= 0) {
death();
} else {
enemyBasicAttack();
if (playerCurrHealth <= 0) {
death();
}
}
}
}
//Player combat systems
private static void playerBasicAttack() {
OutputPanel.output.append("\n Your attack does " + playerAttack + " damage to the enemy!");
enemyCurrHealth -= playerAttack;
gainPlayerRage();
gainEnemyRage();
statusUpdate();
}
//Player kick attack
public static void playerKickAttack() {
OutputPanel.output.append("\n Your kick does " + playerKick + " damage to the enemy!");
enemyCurrHealth -= playerKick;
gainPlayerRage();
gainEnemyRage();
statusUpdate();
Random random = new Random();
int kickChance = random.nextInt(100) + 1;
if (kickChance >= 60) {
OutputPanel.output.append("\n Your kick has stunned the enemy!");
} else {
enemyBasicAttack();
gainEnemyRage();
gainPlayerRage();
statusUpdate();
}
}
//Player power attack
public static void playerPowAttack() {
OutputPanel.output.append("\n Your POWER ATTACK does " + playerPowAttack + " damage to the enemy!");
enemyCurrHealth -= playerPowAttack;
playerCurrRage = 0;
gainEnemyRage();
statusUpdate();
BottomButtons.powAttButton.setEnabled(false);
}
private static void gainPlayerRage() {
if (playerCurrRage < 100) {
playerCurrRage += 5;
if (playerCurrRage >= 100) {
playerCurrRage = 100;
BottomButtons.powAttButton.setEnabled(true);
} else {
BottomButtons.powAttButton.setEnabled(false);
}
}
}
//Enemy combat systems
private static void enemyBasicAttack() {
OutputPanel.output.append("\n Enemy's attack does " + enemyAttack + " damage to you!");
playerCurrHealth -= enemyAttack;
gainEnemyRage();
gainPlayerRage();
statusUpdate();
}
private static void gainEnemyRage() {
if (enemyCurrRage < 100) {
enemyCurrRage += 5;
} else {
enemyCurrRage = 100;
}
}
//END GAME
private static void death() {
if (playerCurrHealth <= 0) {
Loop.combatDisabled();
fighting = false;
loseGame();
} else if (enemyCurrHealth <= 0) {
if (!Loop.enemyList.isEmpty()) {
Loop.enemyList.remove(0);
OutputPanel.output.append("\nYou have killed an enemy!");
statusUpdate();
fighting = true;
} else {
fighting = false;
Loop.combatDisabled();
winGame();
}
}
}
private static void winGame() {
OutputPanel.output.setText("You won!");
Loop.combatDisabled();
Loop.currLevel++;
Loop.enemyList.clear();
Loop.newGame();
}
private static void loseGame() {
OutputPanel.output.setText("You lost!");
Loop.combatDisabled();
}
}
Generally, the right way to do this is to create an instance of a class that is called a controller. A controller is an object that handles references to other objects and handles out the tasks to be done. So, in your main, you do something like
GameController cont = new GameController();
Then, if you need something that the controller requires access to, just link it inside the controller:
GUI gui = new GUI();
cont.setGUI(gui);
Also, whenever something will need to access the controller to do its work, you need to provide it with the controller:
gui.setController(controller);
This way, you provide abstraction - you do not call eg. GUI drawing from within your player character, you just create methods within the controller such as say handlePlayerInput(...) and the controller knows what objects to call and what methods to handle.
"Everything static" is not a bad programming paradigm per se, however it usually signals heavy-coupled and inflexible architecture. For example, should you have two enemyLists, what would you do? Another static field would probably do but it would require a lot of copy-paste for all things that use enemyList right now. Copy-pasting is usually the thing you want to avoid so as to make long-term maintenance easier.
Better architectures encapsulate things into meaningful abstractions, either object-oriented or somehow else representing modules with single responsibilities. Game logic and rendering are usually separate things. As is said in a another answer by #PiotrWilkin, many implementations encapsulate top-level components into a controller while those components themselves manage other related things.
If you are interested in software design and architecture, I would suggest reading the following two classics:
Principles and Patterns by Robert C. Martin, a detailed explanation of SOLID design principles, simple to learn yet hard to master concepts that together help making rock-solid software architectures.
Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides with a foreword by Grady Booch. This is a dictionary-like book, describing patterns commonly applied in software design.

How can I update JPanel continuously?

I've got a slight problem, I'm writing a gps tracking app to track several objects at once. The data comes in over a serial interface, this is coming in fine from what I can tell. The issue is that I need to continually update the JPanel where the map is created and displayed.
public JPanel mapDisplay(){
JPanel mapPanel = new JPanel();
mapPanel.setSize(560, 540);
Coordinate start = new Coordinate (-34.9286, 138.6);
trackMap.addMapMarker(new MapMarkerDot(1Lat, 1Lon));
trackMap.setDisplayPosition(start,8);
System.out.println(1Lat);
mapPanel.add(trackMap);
mapPanel.setVisible(true);
return mapPanel;
}
This is what I have and it's happy to display the point once but won't update. If I print out the 1Lat variable in the serial method it continually prints, however it only does it once here.
A lot of the answers I've found refer to setting markers by arrays, however that won't work in this case as the objects I'm tracking could be anywhere.
Any help would be greatly appreciated :)
Is it possible to use a worker thread and not use an ArrayList? I would run the risk of missing data if I do.
Not necessarily. In a SwingWorker, your implementation of the doInBackground() method can publish() results as they become available. Note in particular that "Results from multiple invocations of publish() are often accumulated for a single invocation of process()." In your process(), simply loop through the List<Coordinate>, update the route and repaint() the map.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import org.openstreetmap.gui.jmapviewer.Coordinate;
import org.openstreetmap.gui.jmapviewer.JMapViewer;
import org.openstreetmap.gui.jmapviewer.MapPolygonImpl;
/**
* #see http://stackoverflow.com/a/37193636/230513
*/
public class MapWorkerTest {
private final List<Coordinate> route = new ArrayList<>();
private void display() {
JFrame f = new JFrame("MapWorker");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMapViewer map = new JMapViewer() {
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
#Override
public String getToolTipText(MouseEvent e) {
Coordinate c = (Coordinate) getPosition(e.getX(), e.getY());
return c.getLat() + " " + c.getLon();
}
};
map.setToolTipText("");
Coordinate start = new Coordinate(-34.9286, 138.6);
route.add(start);
MapPolygonImpl poly = new MapPolygonImpl(route);
poly.setColor(Color.blue);
map.addMapPolygon(poly);
map.setDisplayPosition(start, 10);
f.add(map);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
new MapWorker(map, start).execute();
}
private class MapWorker extends SwingWorker<Void, Coordinate> {
private final JMapViewer map;
private Coordinate last;
public MapWorker(JMapViewer map, Coordinate start) {
this.map = map;
this.last = start;
}
#Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
last = new Coordinate(last.getLat() + 0.0025, last.getLon() + 0.01);
publish(last);
Thread.sleep(1000);
}
return null;
}
#Override
protected void process(List<Coordinate> chunks) {
for (Coordinate c : chunks) {
route.add(c);
}
map.repaint();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new MapWorkerTest()::display);
}
}
Multiple route management left as a exercise.

Why I cannot refresh contents of ListWindow

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.

JMapViewer ADD tiles for offline view

Hello I'm using this sample in Java to try to load OpenStreetMaps Offline tiles,
for example I have my tiles on C:/OSM/tiles/
but I need to know how to add this information in map (JMapViewer) class to load tiles locally.
Thank you very much for your help this is my source:
//License: GPL. Copyright 2008 by Jan Peter Stotz
import org.openstreetmap.gui.jmapviewer.JMapViewer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
*
* Demonstrates the usage of {#link JMapViewer}
*
* #author Jan Peter Stotz
*
*/
public class Demo extends JFrame {
public Demo() {
super("JMapViewer Demo");
setSize(400, 400);
final JMapViewer map = new JMapViewer();
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
JPanel panel = new JPanel();
add(panel, BorderLayout.NORTH);
final JCheckBox showMapMarker = new JCheckBox("Map markers visible");
showMapMarker.setSelected(map.getMapMarkersVisible());
showMapMarker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
map.setMapMarkerVisible(showMapMarker.isSelected());
}
});
panel.add(showMapMarker);
final JCheckBox showTileGrid = new JCheckBox("Tile grid visible");
showTileGrid.setSelected(map.isTileGridVisible());
showTileGrid.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
map.setTileGridVisible(showTileGrid.isSelected());
}
});
panel.add(showTileGrid);
final JCheckBox showZoomControls = new JCheckBox("Show zoom controls");
showZoomControls.setSelected(map.getZoomContolsVisible());
showZoomControls.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
map.setZoomContolsVisible(showZoomControls.isSelected());
}
});
panel.add(showZoomControls);
add(map, BorderLayout.CENTER);
//
// map.addMapMarker(new MapMarkerDot(49.814284999, 8.642065999));
// map.addMapMarker(new MapMarkerDot(49.91, 8.24));
// map.addMapMarker(new MapMarkerDot(49.71, 8.64));
// map.addMapMarker(new MapMarkerDot(48.71, -1));
// map.addMapMarker(new MapMarkerDot(49.807, 8.644));
map.setDisplayPositionByLatLon(-0.223056, -78.5126, 11);
}
/**
* #param args
*/
public static void main(String[] args) {
new Demo().setVisible(true);
}
}
A much better alternative that doesn't require modifying JMapViewer and recompiling it is to provide your own TileSource implementation, as shown here.
Grab the OfflineOsmTileSource, and use it like the blog post says.
Simple and elegant. All you need is some osm tiles stored locally, which I assume you already have.
As far as I remember JMapViewer is designed to work only using online maps.
Changing that behavior seams to be complicated. May be you can achieve this by implementing your own org.openstreetmap.gui.jmapviewer.TileLoader instance. The implementation only has to be able to create Runnable instances that load a specific tile into the TileCache and inform the registered TileLoaderListener that a tile loading is completed.
I compile by the source directly and change
\org\openstreetmap\gui\jmapviewer\tilesources\AbstractOsmTileSource.java
Here is the source code inside JMapViewer.zip/JMapViewer_src.jar extract the Jar file and copy the folder /org in the mail source code folder
http://svn.openstreetmap.org/applications/viewer/jmapviewer/releases/2011-02-19/JMapViewer.zip
and change the next
public AbstractOsmTileSource(String name, String base_url, String attr_img_url) {
this.name = name;
// this.baseUrl = base_url;
this.baseUrl = "file:///C:/OSM/tiles";
attrImgUrl = attr_img_url;
}
I have no idea if this approach wasn't supported back when this thread happened, but for caching offline tiles they provide OsmFileCacheTileLoader;
http://josm.openstreetmap.de/doc/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.html
It is super easy to use.
this.mapViewer = new JMapViewer();
OsmFileCacheTileLoader ofctl;
try {
File cacheDir = new File(System.getProperty("user.home"), "OpenStreetMapTileCache");
logger.info("Home Directory = " + System.getProperty("user.home") + ", cacheDir=" + cacheDir);
cacheDir.mkdirs();
ofctl = new OsmFileCacheTileLoader(mapViewer, cacheDir);
this.mapViewer.setTileLoader(ofctl);
} catch (IOException ex) {
Logger.getLogger(MapDisplayPanel.class.getName()).log(Level.SEVERE, "Exception creating OsmFileCacheTileLoader" + ex, ex);
}

Categories

Resources