📄 jcanvas3d.java
字号:
* Creates a new instance of JCanvas3D. Resize mode is set * to RESIZE_IMMEDIATELY and validation delay to 100ms. * * @param graphicsConfiguration The graphics configuration to be used. * @param lwCanvas the lightweight canvas that is linked to that * heavyweight canvas. */ public InternalCanvas3D(GraphicsConfiguration graphicsConfiguration, JCanvas3D lwCanvas) { super(graphicsConfiguration, true); this.lwCanvas = lwCanvas; imageReadyBis = false; waitingForSwap = false; addNotifyFlag = false; } /** * {@inheritDoc} */ public void addNotify() { if (false == addNotifyFlag) { throw new UnsupportedOperationException("CHANGE ME"); } else { addNotifyFlag = false; super.addNotify(); } } /** * Normally, returns the parent of that component. As the * canvas ought to never be added to any component, it has no parent. * Java 3D expects it to have a parent for some operations, so we in * fact cheat it by returning the parent of the lightweight component. * * @return the parent of the lightweight component, if any. Returns * null if the component is not created or if it has no * parent. */ public java.awt.Container getParent() { if (null == this.lwCanvas) { return null; } return this.lwCanvas.getParent(); } /** * Blocks the retrieval of the render buffer. */ public void postRender() { imageReadyBis = false; } /** * Retrieves the buffer from canvas, if possible, and * calls/notifies component to be repainted, if necessary. */ synchronized public void postSwap() { if (true == isRendererRunning()) { // as weird as it can look, there can be postswaps without rendered running. (?!!) Anyway, in that case we should not refresh. bi = getOffScreenBuffer().getImage(); imageReadyBis = true; if (false == waitingForSwap) { // System.err.println("repaint " + System.currentTimeMillis()); this.lwCanvas.repaint(); } else { notify(); } } else { // System.err.println("SWAP WITHOUT RENDERER RUNNING"); } } /** * Overriden so that the JComponent can access it. * * @param e {@inheritDoc} */ protected void processComponentEvent(java.awt.event.ComponentEvent e) { super.processComponentEvent(e); } /** * Overriden so that the JComponent can access it. * * @param e {@inheritDoc} */ protected void processFocusEvent(java.awt.event.FocusEvent e) { super.processFocusEvent(e); } /** * Overriden so that the JComponent can access it. * * @param e {@inheritDoc} */ protected void processInputMethodEvent( java.awt.event.InputMethodEvent e) { super.processInputMethodEvent(e); } /** * Overriden so that the JComponent can access it. * * @param e {@inheritDoc} */ protected void processKeyEvent(java.awt.event.KeyEvent e) { super.processKeyEvent(e); } /** * Overriden so that the JComponent can access it. * * @param e {@inheritDoc} */ protected void processMouseEvent(java.awt.event.MouseEvent e) { super.processMouseEvent(e); } /** * Overriden so that the JComponent can access it. * * @param e {@inheritDoc} */ protected void processMouseMotionEvent(java.awt.event.MouseEvent e) { super.processMouseMotionEvent(e); } /** * Overriden so that the JComponent can access it. * * @param e {@inheritDoc} */ protected void processMouseWheelEvent(java.awt.event.MouseWheelEvent e) { super.processMouseWheelEvent(e); } /** * If the Canvas is in a state that forbids the retrieving * of the buffer, wait a bit before trying again. */ synchronized void waitForSwap() { int counter = MAX_WAIT_LOOPS; while (false == imageReadyBis) { try { waitingForSwap = true; wait(MAX_WAIT_TIME); waitingForSwap = false; if (!imageReadyBis && --counter <= 0) { //if i've waited too long for the canvas to be there, let us declare it crashed. System.err.println("CANVAS CRASHED!!!"); canvasCrashed = true; return; } } catch (InterruptedException ex) { System.err.println(ex); } } } } /** * This Runnable is the class used when the canvas has to be * resized. */ static class ResizeSwingRunnable implements Runnable { /** The component that is displaying the canvas */ JCanvas3D canvas; /** latest height that was requested */ int height; /** latest width that was requested */ int width; /** * Creates a new ResizeSwingRunnable object. */ private ResizeSwingRunnable() { } /** * Creates a new ResizeSwingRunnable object. * * @param canvas the canvas to check * @param width the width that is requested * @param height the height that is requested */ public ResizeSwingRunnable(JCanvas3D canvas, int width, int height) { this.canvas = canvas; this.width = width; this.height = height; } /** * {@inheritDoc} */ public void run() { canvas.createCanvas(width, height); } } /** * This Thread handles the resizing changes and handles the timer * up to the moment when the resizing has to really occur. */ static class ResizeThread extends Thread { //TODO: refactor so that it can handle a list of canvases, delays and start delay date, and change to a singleton. Actually, each JCanvas3D that would have to resize would spawn its own thread, which ought to be seen as "a bad thing" /** the canvas that has to be checked */ JCanvas3D canvas; /** A flag indicating that since last check, size got changed again and the delay has to be reset */ boolean sizeChanged; /** the delay that has to occur between last size change and real resize */ int delay; /** latest height that was requested */ int height; /** latest width that was requested */ int width; /** * Creates a new ResizeThread object. */ private ResizeThread() { } /** * Creates a new ResizeThread object. * * @param width initial width change * @param height initial height change * @param delay delay to be used * @param canvas the canvas that has to be checked */ public ResizeThread(int width, int height, int delay, JCanvas3D canvas) { this.width = width; this.height = height; this.delay = delay; this.sizeChanged = true; this.canvas = canvas; } /** * returns the latest height that is being requested for change * * @return latest height requested */ public int getHeight() { return height; } /** * returns the latest width that is being requested for change * * @return latest width requested */ public int getWidth() { return width; } /** * {@inheritDoc} */ public void run() { try { while (true == sizeChanged) // the double loop is made so that if a change of size arrives while the canvas is already resizing, the same thread can keep up with subsequent resizes. { // the effect of the double loop is to simplify some subtle race conditions at higher level. while (true == sizeChanged) { sizeChanged = false; Thread.sleep(delay); // while the thread sleeps, value can change. if value changes, flag will be true, and i'll have to wait again. if size does not change during the sleep, thread will quit and size will change. //TODO: should i force a resize after a definite delay occured, so it does not stay zoomed too long ? } try { EventQueue.invokeAndWait(new ResizeSwingRunnable( canvas, width, height)); } catch (InterruptedException ie) { } catch (InvocationTargetException ite) { } } } catch (InterruptedException ie) { //if i get interrupted, this is not important, i'll quit method. } } /** * sets height. this has the effect of resetting the timeout. * * @param height the new height. * * @throws RuntimeException DOCUMENT ME! */ public void setHeight(int height) { if (isAlive()) { this.height = height; sizeChanged = true; } else { throw new RuntimeException( "Resizing order arrived to a dead resizing thread. Spawn a new one."); } } /** * Sets width. This has the effect of resetting the timeout. * * @param width the new width. * * @throws RuntimeException DOCUMENT ME! */ public void setWidth(int width) { if (isAlive()) { this.width = width; sizeChanged = true; } else { throw new RuntimeException( "Resizing order arrived to a dead resizing thread. Spawn a new one."); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -