whiteboard.java
来自「white board」· Java 代码 · 共 2,132 行 · 第 1/3 页
JAVA
2,132 行
else if (e.id == Event.KEY_PRESS) { // Set color to the current color g.setColor(tools.colorPaletteTool.curColor()); bg.setColor(tools.colorPaletteTool.curColor()); // Set the font to the current font g.setFont(tools.fontSelector.curFont()); bg.setFont(tools.fontSelector.curFont()); System.out.println("Font is " + tools.fontSelector.curFont().getName()); // Draw the character c[0] = (char)(e.key); g.drawChars(c, 0, 1, startX, startY); bg.drawChars(c, 0, 1, startX, startY); // Advance the X-position startX += g.getFontMetrics().charWidth(e.key); } } /** * Return the name of this tool. */ public String getToolName() { return toolName; }}/** * Allow the user to draw freehand, as with a pencil. Use the current color * and line width. */class PencilTool extends ToolCanvas{ final static String toolName = "PencilTool"; final static int toolId = 6; // Tool state: int curX, curY; private int iconX[] = {4, 7, 9, 12, 16, 18}; private int iconY[] = {4, 12, 8, 14, 10, 11}; /** * Construct the pencil tool. */ public PencilTool(Tools t) { super(t); setBackground(Color.yellow); resize(width, height); dim.width = width; dim.height = height; } Dimension getDimension() { return dim; } /** * (Re)paint the pencil tool icon. */ public void paint(Graphics g) { g.setColor(Color.white); g.fill3DRect(0, 0, width-1, height-1, true); g.setColor(Color.black); g.drawPolygon(iconX, iconY, iconX.length); } /** * Draw an dot, using the current line tool attributes */ public void drawDot(Graphics g) { // Make this reflect the current width and color... g.setColor(tools.colorPaletteTool.curColor()); // Draw a filled oval, of the correct thickness int w = tools.lineWidthTool.curLineWidth(); g.fillOval(curX - w/2, curY - w/2, w, w); } /** * Apply the pencil tool to the canvas and the double buffer. */ public void applyTool(Event e, Graphics g, Graphics bg) { super.applyTool(e, g, bg); if ((e.id == Event.MOUSE_DOWN) || (e.id == Event.MOUSE_DRAG)) { // Set current location... curX = e.x; curY = e.y; // Draw a dot at the current location g.setPaintMode(); drawDot(g); // Update the off-screen buffer bg.setPaintMode(); drawDot(bg); } } /** * Return the name of this tool. */ public String getToolName() { return toolName; }}/** * A class for assembling the tools. Maintains the "current tool". */class Tools{ ToolCanvas curTool; // the current tool // // These are all the tools... // LineWidthTool lineWidthTool; ColorPaletteTool colorPaletteTool; LineTool lineTool; BoxTool boxTool; OvalTool ovalTool; FontSelector fontSelector; TextTool textTool; PencilTool pencilTool; /** * Construct the tool assembler */ public Tools() { lineWidthTool = new LineWidthTool(this); colorPaletteTool = new ColorPaletteTool(this); lineTool = new LineTool(this); boxTool = new BoxTool(this); ovalTool = new OvalTool(this); fontSelector = new FontSelector(this); textTool = new TextTool(this); pencilTool = new PencilTool(this); setCurTool(lineTool); } /** * Return the current tool */ public ToolCanvas getCurTool() { return curTool; } /** * Set the current tool */ public void setCurTool(ToolCanvas t) { curTool = t; System.out.println("Current tool is " + t.getToolName()); } public ToolCanvas getTool(int id) { switch (id) { case LineWidthTool.toolId: return lineWidthTool; case ColorPaletteTool.toolId: return colorPaletteTool; case LineTool.toolId: return lineTool; case BoxTool.toolId: return boxTool; case OvalTool.toolId: return ovalTool; case PencilTool.toolId: return pencilTool; case FontSelector.toolId: return fontSelector; case TextTool.toolId: return textTool; default: return null; } }}/** * A panel of tools. */class ToolPanel extends Panel{ Tools tools; /** * Construct the tool panel. */ public ToolPanel(Tools t) { tools = t; setBackground(Color.blue); // Layout the tools, individually add(tools.lineWidthTool); add(tools.colorPaletteTool); add(tools.lineTool); add(tools.boxTool); add(tools.ovalTool); add(tools.pencilTool); add(tools.fontSelector); add(tools.textTool); }}/** * The painting canvas. */class MainCanvas extends Canvas{ Tools tools; // the user's toolkit Tools cmdTools; // the paint monitor's tools Whiteboard whiteboard; // the owning applet Image buffer; // the double buffer Graphics bg; // the graphics context of the buffer Color canvasBackgroundColor = Color.white; /** * Construct the canvas. */ public MainCanvas(Tools t, Tools ct, Whiteboard p) { tools = t; cmdTools = ct; whiteboard = p; setBackground(canvasBackgroundColor); } /** * Set up the double buffer */ public void setupBuffer(int w, int h) { System.out.println("Allocating new buffer"); buffer = createImage(w, h); bg = buffer.getGraphics(); bg.setColor(canvasBackgroundColor); bg.fillRect(0, 0, w, h); } /** * Receive canvas events and forward them to the current tool. */ public boolean handleEvent(Event e) { if ((e.id == Event.MOUSE_DOWN) || (e.id == Event.MOUSE_DRAG) || (e.id == Event.MOUSE_UP) || (e.id == Event.KEY_PRESS)) { // Draw image tools.getCurTool().applyTool(e, getGraphics(), bg); // Construct an equivalent command to send to paint server String command = tools.getCurTool().makeCommandString(e); // Send the command to the server, for broadcast to chat clients if (command != null) try {whiteboard.serverConnection.write(command);} catch (IOException ex) { System.out.println("Server unreachable"); } return true; } return super.handleEvent(e); } /** * Apply the command to the graphics context (and buffer), without changing * the state of the canvas. */ public void applyCommand(Command cmd) { ToolCanvas tc = cmdTools.getTool(cmd.toolId); if (tc == null) System.out.println("This tool is not implemented for broadcast"); else tc.applyCommand(cmd, getGraphics(), bg); } /** * (Re)paint the canvas when necessary. */ public void paint(Graphics g) { // Check if window was just resized Dimension d = size(); if ((d.width != buffer.getWidth(this)) || (d.height != buffer.getHeight(this))) { { // Save the currently displayed image Image temp = buffer; // Reallocate a buffer to match the new size setupBuffer(d.width, d.height); // Restore the image to the new buffer bg.drawImage(temp, 0, 0, this); } System.gc(); // force the old buffer to be free'd } // Restore the image to the screen getGraphics().drawImage(buffer, 0, 0, this); } /** * Update the canvas */ public void update(Graphics g) { paint(g); }}/** * Helper class for managing a server connection. */class ServerConnection{ String hostname; int port; Socket socket; DataInputStream dis; DataOutputStream dos; final static int MAXLENGTH = 5000; protected byte inbuf[] = new byte[MAXLENGTH]; protected int nbytes = 0; /** * Establish a connection with a Whiteboard server. */ public void makeConnection(String h, int p) throws java.net.UnknownHostException, IOException { hostname = h; port = p; if (TestData.LOCALMODE) return; socket = new Socket(hostname, port); // Issue confirmation to user InetAddress rina = socket.getInetAddress(); System.out.println("Connected to " + rina.toString()); InetAddress lina = rina.getLocalHost(); System.out.println("Local host designation: " + lina.toString()); // Determine the socket's input and output stream handles dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream()); } /** * Send (the ascii-equivalent of) a string to the server. */ public void write(String s) throws IOException { // Write buffer to the socket if (TestData.TESTMODE) System.out.println("Writing '" + s + "' to server"); if (TestData.LOCALMODE) return; dos.writeBytes(s); // It is peculiar, but the implementation // of this function casts the char data to // bytes, apparently throwing away the upper // eight bits; so we can use it here. } /** * Read a newline-terminated ascii array from the server, and return * its string equivalent. Block until one is found. Throws IOException * if connection is broken before one is found. Uses buffering (and * thus it does not matter if several actual io operations are required * before the newline is found). */ public String readln() // Reads data from the server through the next new-line. throws IOException { if (TestData.TESTMODE) System.out.println("Reading from server..."); if (TestData.LOCALMODE) return TestData.testString; int curpos = 0; for (;;) // until a nl is found { // Check for a nl for (; curpos < nbytes; curpos++) { // if nl, return thru nl, shift remainder down (consume), and return // if ('\n' == (char)(inbuf[curpos])) { // // Consume 0 thru curpos (includes the nl)... // // Construct string... String s = new String(inbuf, 0, 0, curpos+1); // Adjust pointers... nbytes -= (curpos+1); // Shift remaining bytes down to start of inbuf... for (int i = 0; i < nbytes; i++) { // Move nbytes-bytes curpos-positions left inbuf[i] = inbuf[i+curpos]; } return s; } } // Out of bytes and no nl... // Perform another read, into inbuf, starting at curpos... int n = dis.read(inbuf, curpos, MAXLENGTH-nbytes); if (n <= 0) { // No more data, and no nl found... throw new IOException(); } nbytes += n; } }}/** * Monitor the server connection for paint commands, and execute them when they * are received. */class PaintMonitor extends Thread{ Whiteboard whiteboard; public PaintMonitor(Whiteboard p) { whiteboard = p; } public void run() { // Perform blocking reads on server connection for (;;) { String s; try {s = whiteboard.serverConnection.readln();} catch (IOException ex) { // Connection is probably broken... System.out.println("Unable to read from server"); return; } // // Interpret the command // if (TestData.TESTMODE) System.out.println("Command received: '" + s + "'"); Command cmd = null; try {cmd = new Command(s);} catch (Exception ex) { System.out.println("Invalid command received from server"); continue; } whiteboard.mainCanvas.applyCommand(cmd); } }}/** * The applet. */public class Whiteboard extends Applet{ // The main components: LayoutManager layoutManager; MainCanvas mainCanvas; Panel toolPanel; Frame mainFrame; Tools tools; Tools cmdTools; ServerConnection serverConnection; PaintMonitor paintMonitor; /** * Construct the applet */ public Whiteboard() { // Call the superclass constructor (for Applet) super(); // Instantiate the tools tools = new Tools(); cmdTools = new Tools(); // // Construct the canvas // mainCanvas = new MainCanvas(tools, cmdTools, this); // // Construct the tool panel // toolPanel = new ToolPanel(tools); // // Lay out the constructed applet components in the applet... // // Create a Border Layout setLayout(new BorderLayout()); // Layout the tool panel add("North", toolPanel); // Layout the canvas add("Center", mainCanvas); mainCanvas.resize(200, 100); // Create the server connection object serverConnection = new ServerConnection(); // Create the server monitor paintMonitor = new PaintMonitor(this); } /** * After all objects have been constructed, and the applet context exists: */ public void init() { super.init(); // Check our assumptions about the applet context... mainFrame = (Frame)(getParent()); if (! (getParent() instanceof Frame) ) System.exit(1); // Set up the drawing canvas double-buffer (needs the final canvas size) mainCanvas.resize( ConfigData.FRAME_INITIAL_WIDTH, ConfigData.FRAME_INITIAL_HEIGHT); Dimension d = mainCanvas.size(); mainCanvas.setupBuffer(d.width, d.height); // Establish connection with Whiteboard server try {serverConnection.makeConnection( ConfigData.DEFAULT_HOST_NAME, ConfigData.DEFAULT_PORT_NUMBER);} catch (Exception ex) { System.out.println("Unable to make connection to Paint server"); return; } // Start the monitor paintMonitor.start(); } /** * Start or restart the applet: */ public void start() { super.start(); } /** * Sleep the applet: */ public void stop() { super.stop(); } /** * Handle applet events */ public boolean handleEvent(Event e) { // The kill-window event... if (e.id == Event.WINDOW_DESTROY) { System.exit(0); } return super.handleEvent(e); } /** * (Re)paint the applet */ public void paint(Graphics g) { super.paint(g); } /** * Main routine, for running as an application. */ public static void main(String args[]) { // Create a Frame MainFrame f = new MainFrame("Whiteboard"); // Instantiate the Applet Whiteboard applet = new Whiteboard(); // Add the Applet to the Frame (Frame's use BorderLayout) f.add("Center", applet); // Resize and show the Frame f.resize(ConfigData.FRAME_INITIAL_WIDTH, ConfigData.FRAME_INITIAL_HEIGHT); f.show(); // Init and start the Applet applet.init(); applet.start(); }}/** * Define a frame that can be destroyed. */class MainFrame extends Frame{ public MainFrame(String s) { super(s); } // Handle close events by simply exiting public boolean handleEvent(Event e) { if (e.id == Event.WINDOW_DESTROY) { System.exit(0); } return false; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?