I am rendering a model on canvas with opengl, therefore using a while loop and I run it under a thread not to disturb the main thread. I also have a text Field where I want to write some text. The text field focuses to my action and takes input but when hovering through the canvas, the text field focuses but I am not able to write something on it. This may be because of the the while loop but I do not know how to overcome this. I want the ui to remain responsive.
Here is my code:
import java.awt.Canvas;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextField;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.PixelFormat;
public final class Loader extends JFrame {
public final int FPS = 120; // better cause of animations
public static Loader loader;
public Canvas canvas;
private Viewport viewport;
private JTextField textField;
private Loader() {
setTitle("Test");
setResizable(true);
setSize(320, 285);
setLocationRelativeTo(null);
getContentPane().setLayout(null);
setVisible(true);
canvas = new Canvas();
getContentPane().add(canvas);
canvas.setBounds(10, 24, 280, 163);
textField = new JTextField();
textField.setColumns(10);
textField.setBounds(91, 193, 116, 22);
getContentPane().add(textField);
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
// Initialize the frame
loader = new Loader();
new Thread(new Runnable() {
@Override
public void run() {
try {
// render the model
loader.render();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private static void init(Canvas canvas) throws Exception {
Display.setParent(canvas);
try {
Display.create(new PixelFormat(8, 24, 8, 8));
} catch (Exception ex) {
Display.create(new PixelFormat(8, 24, 8, 0));
}
Display.makeCurrent();
Display.setVSyncEnabled(false);
Display.setSwapInterval(0);
}
private void render() throws Exception {
init(canvas);
loader.viewport = new Viewport(canvas);
long[] timerCache = new long[10];
long timerCur = 0L;
long timerDst = 0L;
long timerLast = 0L;
long timerRate = 1000000L * 1000L / FPS;
int timerCacheIndex = 0;
int timerCacheSize = 0;
boolean minSleep = Runtime.getRuntime().availableProcessors() <= 1;
long[] clockCache = new long[32];
int clockIndex = 0;
int fps = 0;
while (isVisible()) {
long clock = System.nanoTime();
long lastClock = clockCache[clockIndex];
clockCache[clockIndex] = clock;
if (++clockIndex == 32)
clockIndex = 0;
if (lastClock != 0L && clock > lastClock) {
fps = (int) (1000000L * 1000L * 32L / (clock - lastClock));
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(.5f, .6f, .9f, 1f);
loader.viewport.render();
if (minSleep)
try {
Thread.sleep(1L);
} catch (Exception ex) {
}
timerCache[timerCacheIndex++] = System.nanoTime();
if (timerCacheSize < timerCacheIndex)
timerCacheSize = timerCacheIndex;
if (timerCacheIndex == 10)
timerCacheIndex = 0;
long time = 0L;
for (int i = 0; i != timerCacheSize; time += timerCache[i++])
;
time /= (long) timerCacheSize;
if (timerCacheSize == 1)
timerLast = time;
timerCur += time - timerLast;
timerLast = time;
timerDst += timerRate;
if (timerDst > timerCur) {
long sleep = timerDst - timerCur;
try {
Thread.sleep(sleep / 1000000L, (int) (sleep % 1000000L));
} catch (Exception ex) {
}
timerCur = timerDst;
for (int i = 0; i != timerCacheSize; ++i)
timerCache[i] += sleep;
timerLast += sleep;
}
}
}
}
This gif may help know how it currently looks. https://gyazo.com/e6950fd8dd01306c704857e94f214f93.gif
I don't see where is the mistake in here, I already use a thread for the render method.
Edit:
Viewport.java
public Viewport(Canvas canvas) throws LWJGLException {
this.canvas = canvas;
this.scale = 1.0F;
this.pitch = 180.0F;
this.yaw = 0.0F;
this.roll = 0.0F;
}
public void render() {
try {
Dimension size = canvas.getSize();
if (models != null && size.width > 0 && size.height > 0) {
if (width != size.width || height != size.height) {
width = size.width;
height = size.height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float c = (float) Math.sqrt((double) (width * width) + (double) (height * height));
glOrtho(0.0F, (float) width, 0.0F, (float) height, -c, c);
glMatrixMode(GL_MODELVIEW);
}
if (Mouse.isButtonDown(0) && !Mouse.isButtonDown(1)) {
yaw -= (float) Mouse.getDX() / 2;
pitch -= (float) Mouse.getDY() / 2;
}
if (Mouse.isButtonDown(0) && Mouse.isButtonDown(1)) {
offset_z += (float) Mouse.getDY();
}
float wheel = (float) Mouse.getDWheel() / 1800.0F;
if (wheel > 1.0F)
wheel = 1.0F;
else if (wheel < -1.0F)
wheel = -1.0F;
scale += scale * wheel;
if (scale < 0.01F)
scale = 0.01F;
for (Model3D model : models) {
float x = (float) width / 2.0F;
float y = ((float) -((100.0F * (scale))) + offset_z) + (float) (height - model.height()) / 2.0F;
float z = 0.0F;
model.render(model, x, y, z, pitch, yaw, roll, scale, scale, scale);
}
Display.update();
}
} catch (Throwable t) {
}
}
Instead of:
new Thread(new Runnable() {
@Override
public void run() {
try {
// render the model
loader.render();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
maybe:
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
// render the model
loader.render();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
It will run at AWT dispatching thread, maybe the issue will fade. Swing not being thread safe sometimes makes life hard.
您可以尝试将requestFocus()
添加到Loader
类的render()
方法的末尾并报告发生的情况吗?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.