MultiThread in drawing?

Anyone knows how to use MultiThread to draw line, circle etc. at the same time? That is, how can I create MultiThread in paint(graphics d) method? Thanks.

Hi,
I'd a quick look at your graphics forum question, but haven't done anything like that.
That's more in the area of image interpretation, object recognition.
You might have more luck directing your searches and questions in that area.
Depending on whether you wanted to detect one or more simple geometric shapes, there's certain image transforms you can do for "edge detection". That should create a crude line drawing of any image.
After that, you perform any detection routines.
That's all the help I can give in this area, use the keywords I mentioned to find more.
regards,
Owen

Similar Messages

  • Multithreading

    I have a program which displays 4 plots that plot x-data against time on the y-axis. I also have a timer set up to every "x" seconds, check a directory for any new XML files, if there are new files, parse them and retrieve all the data from the files. Then I add the data to each plot for the new data points and then tell each plot to update. With all this happeneing every couple seconds, the rest of my GUI is pretty much inoperable, such as changing what data to display along the x-axis and changing the preferences in the preferences dialog. I thought maybe I should multithread my application, maybe making each of the plots a thread so I would have 5 total threads, 1 to handle the main application, user inputs, checking for files, and reading in files, and the other 4 threads, 1 for each plot, to handle the drawing. I could possibly create a 6th thread to handle the checking for and reading in of files, but for right now I want to focus on making the plots each a thread. I have read through some examples of threading online but am having some difficulties.
    Each plot extends the JPanel class, so I know I need to make each plot implement Runnable. Before trying to thread the Plots, I had the plot object implement the paintComponent method to handle the drawing of the data. I used a Graphics2D object to do the rendering of the grid, axes, and data. What I am having problems figuring out is what I should be putting into the run method? Should I run paintComponent from run( ) or do I not want to implement paintComponent anymore? Any ideas would be greatly appreciated as to what I need to do to handle this problem. If you need some more information, please let me know what I can tell you to help you further understand my issue.
    Thanks!

    I do have multiple classes, but I probably have not implemented them in the best way. I have a separate class called XMLReader that all it does is parse the XML files. I have a class that extends the JPanel in which my main GUI is created and the timer is created. So maybe before I start threading, I should try to move the timer out of the GUI class and move it into some other class? But what class would I put this in? The structure of my project is such:
    PlotPanel is the JPanel subclass that lays out all the plots on my screen as well as the combo boxes, menu to quit and load the preferences dialog, and a pause/play button for the plots. It also contains the timer, so each time the timer goes off I check for files and parse them and pass the data to the updated plots. It contains multiple ArrayLists of all the data from the files since the user can display x-number of things on the x-axis versus time on the y-axis.
    Plot is a JPanel subclass that overrides the paintComponent method so I can properly draw the Plot. It also contains an ArrayList of DataPoints (x, y, color) which is a simple class containing 4 public members (it would be a struct in C/C++).
    XMLReader is a class that has a parse function that takes in a filename and it parses the file and stores the data. PlotPanel then stores the data from the file XMLReader just parsed and PlotPanel then adds the new DataPoint to the proper Plot.
    I also have a Configuration class which is a singleton class that all the other classes access to look for the input directory, and other configurable items.
    PreferencesPanel is a way to modify the Configuration instance and is accessible from the File Menu inside PlotPanel.
    I do create a JFrame inside PlotPanel that displays the PlotPanel and I am thinking I should move this back outside PlotPanel like I originally had done. But my biggest concern is where would I put the timer to get it outside the PlotPanel? Right now, when the timer goes off inside PlotPanel, I check to see if there are any new files in the input directory, and if there are I loop through the list of files and parse each one, then update each Plot by adding the new DataPoints. So I think I should structure this better before attempting to thread it, but the tutorials provided in the previous post seem like they will be much better than the little bit of information one of my books contained. Thanks for all your help!

  • How are static methods handled in a multithreaded application?

    hi
    i have a class Drawer with a static method public static draw(Graphics g). now assume there are more thrads callin at the same time Drawer.draw(g). What happens? have some threads to wait until the others have finished calling the method, or can static methods be multithreaded, (can they perform simultaniously)?
    thanks, jo

    ups, i am not drawing on the screen, but in every thread i am drawing a Image. this means before i call the static method in every thread there will be created a BufferedImage and then i pass the Graphics from this images to the static method. also in this case the method performs simultaniously? every thread has its own image and graphics, so the static method should be perform at the same time, isn't it?

  • Multithread in dotnet devkit ?

    Using the dotNet dev kit, I am developing an application which loads ContentDb.
    I have an upload class that has self contained access to a ContentDb. This class works perfectly when run by itself. Each upload class has its own session manager, etc. into contentdb
    In the multithreaded environoment, there are 5 instances of the upload class running.
    After a few instance creations, the connections begin to fail and folder creation fails.
    At this point, even manual folder creation using the browser interface fails, and the ContentDb box needs to be rebooted.
    During updates that do run, there are frequent errors:
    Mar-02 13:23:53:0221,ERROR,,Error Creating Definition PDG22711792007-02-09-18.23.56.262000.PDFSystem.Net.WebException: The request failed with HTTP status 409: Conflict.
    at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
    at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
    at oracle.ifs.fdk.impl.SessionManagerService.beginTransaction()
    at oracle.ifs.fdk.impl.SessionManagerImpl.beginTransaction()
    at oracle.ifs.fdk.impl.FileManagerImpl.createDocumentDefinitions(NamedValueSet[] defs, AttributeRequest[] attributes)
    at oracle.ifs.fdk.impl.FileManagerImpl.createDocumentDefinition(NamedValue[] def, AttributeRequest[] attributes)
    at ImageServer2.ClsContentDb.AddDocument(String p_CDbLibraryFolderPath, String p_CDbDocumentName, String p_FilePathAndName, String[] p_Attributes) in C:\ImageServer\Development\ContentDb_Access\ClsContentDb.cs:line 232,,
    Is the dotNet dev kit threadsafe?
    What can I do to avoid or recover from the conflict errors?
    Thank you

    This was likely a result of FdkException
    ORACLE.FDK.SessionError
    ORACLE.FDK.MaximumConcurrentRequestsPerUserReached
    Edit the HTTP Node Configurations (OC4J_Content) and alter the Maximum Concurrent Requests Per User value to the size of the max number of concurrent worker threads of your application for a particular user concerned.
    Here is some pretty useful sample code showing creation of a Content DB connection pool - and also demonstrating multitple concurrent uploads :-
    -Matt
    ConnectionPool.cs
    * Copyright (c) 2007, Oracle. All rights reserved.
    * History:
    *  2007-03-09  Matt Shannon
    * Note - If receiving ORACLE.FDK.SessionError:ORACLE.FDK.MaximumConcurrentRequestsPerUserReached
    * one must edit the OC4J_Content (HTTP) Node Configuration - and change the
    * "Maximum Concurrent Requests Per User" value to at least the max connections size
    * specified for this ConnectionPool class!  OC4J_Content must then be bounced.
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using oracle.ifs.fdk;
    public class ConnectionPool : IDisposable
      object locker = new object();
      Queue<ManagersFactory> connectionQ = new Queue<ManagersFactory>();
      /// Overall total number of connections that have been allocated
      private int m_AllocatedNum = 0;
      /// Default maximum we permit to be allocated
      private int m_MaxConnections = 10;
      /// Default maximum we permit in the pool; this will be less than m_MaxConnections
      private int m_TargetConnections = 5;
      private FdkCredential m_Credential;
      private string m_Url;
      private StreamWriter m_Writer = null;
      public ConnectionPool(string url, FdkCredential credential) : base()
        m_Url = url;
        m_Credential = credential;
      public ConnectionPool(string url, string username, string password)
        : this(url, new SimpleFdkCredential(username,password))
      public ConnectionPool(
        string url, FdkCredential credential, int target, int max)
        : this(url, credential)
        if (target <= max)
          m_TargetConnections = target;
          m_MaxConnections = max;
      public ConnectionPool(
        string url, string username, string password, int target, int max)
        : this(url, new SimpleFdkCredential(username, password), target, max)
      public void setDebug(StreamWriter writer)
        m_Writer = writer;
        m_Writer.AutoFlush = true;
      private void log(string msg)
        if (m_Writer != null)
          m_Writer.WriteLine(msg);
      private ManagersFactory obtainConnection()
        return ManagersFactory.login(m_Credential, m_Url);
      private bool isSessionValid(ManagersFactory session)
        bool result = false;
        try
          session.getSessionManager().keepAlive();
          result = true;
        catch (FdkException) {}
        // May also get a System.Net.WebException: The request failed with HTTP status 409: Conflict.
        // should maximum concurrent requests per user be reached
        return result;
      public ManagersFactory getSession()
        ManagersFactory sess = null;
        lock (locker)
          if (connectionQ.Count != 0)
            log("Dequeueing session from pool...");
            sess = connectionQ.Dequeue();
            if (!isSessionValid(sess))
              log(" ... session stale from pool - attempting to obtain replacement session...");
              try
                sess = obtainConnection();
                log("Obtained replacement session.");
              catch (FdkException fe)
                log("Attempt to obtain replacement session failed.");
              log(fe.getErrorCode() + ":" + fe.getDetailedErrorCode());
                --m_AllocatedNum;
            else
              log(" ... session good from pool.");
          else if (m_AllocatedNum < m_MaxConnections)
            try
              sess = obtainConnection();
              ++m_AllocatedNum;
              log("Allocated new session.");
            catch (FdkException fe)
              log("Attempt to obtain new session failed.");
              log(fe.getErrorCode() + ":" + fe.getDetailedErrorCode());
          else
            log("No sessions available.");
        return sess;
      public void releaseSession(ManagersFactory sess)
        if (sess == null)
          throw new Exception("Attempt to release null Connection.");
        else
          lock (locker)
            if (!isSessionValid(sess))
              log("Releasing stale session.");
              --m_AllocatedNum;
            else if (connectionQ.Count < m_TargetConnections)
              log("Adding session back to pool.");
              connectionQ.Enqueue(sess);
            else
              log("Disconnecting connection - target size already met.");
              try
                sess.logout();
              catch (FdkException){}
              --m_AllocatedNum;
      public void Dispose()
        log("Disposing ...");
        while (connectionQ.Count != 0)
          ManagersFactory sess = connectionQ.Dequeue();
          try
            log("Calling session logout ...");
            sess.logout();
          catch (FdkException){}
          --m_AllocatedNum;
        log(m_AllocatedNum +" connections remain potentially logged-in.");
      public static void Main(string[] args)
        ArrayList v = new ArrayList();
        using (ConnectionPool pool = new ConnectionPool(
          "http://content1.au.oracle.com:7777/content/ws", "matt", "welcome1", 5, 8))
          pool.setDebug(new StreamWriter(Console.OpenStandardOutput()));
          for (int i=0; i<10 ; i++ )
            ManagersFactory session = pool.getSession();
            if (session != null)
              Console.WriteLine(session.getUser(null).getName());
              v.Add(session);
          foreach (object item in v)
            pool.releaseSession((ManagersFactory)item);
        // Exiting the using statement calls pool's Dispose method - as we implement IDisposable
    }UploadQueue.cs
    * Copyright (c) 2007, Oracle. All rights reserved.
    * History:
    *  2007-03-09  Matt Shannon
    using System;
    using System.Threading;
    using System.Collections.Generic;
    using System.IO;
    using oracle.ifs.fdk;
    public class UploadTask
      private long m_DestinationId;
      private string m_SourcePath;
      private string m_Name;
      public UploadTask(long destinationId, string sourcePath)
        m_DestinationId = destinationId;
        m_SourcePath = sourcePath;
        m_Name = m_SourcePath.Substring(m_SourcePath.LastIndexOf("\\") + 1);
      public string getName()
        return m_Name;
      public long getDestination()
        return m_DestinationId;
      public FileStream getStream()
        FileStream stream = null;
        stream = new FileStream(m_SourcePath,
            FileMode.Open, FileAccess.Read //, FileShare.ReadWrite
        return stream;
    public class UploadQueue : IDisposable {
      object locker = new object();
      Thread[] workers;
      Queue<UploadTask> taskQ = new Queue<UploadTask>();
      ConnectionPool m_Pool;
      public UploadQueue (ConnectionPool pool, int threadCount)
        m_Pool = pool;
        workers = new Thread [threadCount];
        // Create and start a separate thread for each worker
        for (int ii = 0; ii < threadCount; ii++)
          workers[ii] = new Thread(new ThreadStart(Consume));
          workers[ii].Name = "Thread "+ (ii+1);
          workers[ii].Priority = ThreadPriority.Normal;
          workers[ii].Start();
      public void Dispose()
        foreach (Thread worker in workers) EnqueueTask (null);
        foreach (Thread worker in workers) worker.Join();
      public void EnqueueTask (UploadTask task)
        // block until one able to obtain lock
        lock (locker)
          // once lock obtained enqueue task
          taskQ.Enqueue (task);
          // send out pulse
          Monitor.PulseAll (locker);
        } // release lock
      void Consume()
        while (true)
          UploadTask task;
          // block until one able to obtain lock
          lock (locker)
            while (taskQ.Count == 0)
              // Monitor.Wait temporarily releases, or toggles the underlying lock while
              // waiting, so another thread (such as the one performing the Pulse) can obtain it.
              Monitor.Wait (locker);
            task = taskQ.Dequeue();
          } // release lock
          string threadName = Thread.CurrentThread.Name;
          Console.WriteLine(threadName + ":- received task");
          if (task == null)
            return; // This signals our exit
          ManagersFactory session;
          while ((session = m_Pool.getSession()) == null)
            Console.WriteLine(threadName + ":- No session currently available - Sleeping for 1 second ...");
            Thread.Sleep(1000);
          Console.WriteLine(threadName + ":- Obtained session  ...");
          FileManager fileM = session.getFileManager();
          Console.WriteLine(threadName + ":- Creating document definition ...");
          Item docDef = fileM.createDocumentDefinition(
            new NamedValue[]
              ClientUtils.newNamedValue(Attributes.NAME, task.getName()),
              ClientUtils.newNamedValue(
                Options.CONTENTSTREAM, task.getStream()),
            }, null);
          AttributeRequest[] requestedAttributes = null;
          Console.WriteLine(threadName + ":- Creating document ...");
          Item doc = fileM.createDocument(
            new NamedValue[]
              // folder to upload the document to
              ClientUtils.newNamedValue(Options.DESTFOLDER, task.getDestination()),
              // the document should be created using the previously created
              // document definition
              ClientUtils.newNamedValue(
                Options.USE_SAVED_DEFINITION, docDef.getId()),
            }, null, requestedAttributes);
          Console.WriteLine(threadName + ":- File "+doc.getName()+" created with ID "+doc.getId());
          Console.WriteLine(threadName + ":- Releasing session back to pool ...");
          m_Pool.releaseSession(session);
    }A crappy windows app
    Explorer.cs
    * Copyright (c) 2007, Oracle. All rights reserved.
    * History:
    *  2007-03-09  Matt Shannon
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using oracle.ifs.fdk;
    public class Explorer : System.Windows.Forms.Form
      private ListBox uploadBox;
      private ListBox statusBox;
      private System.ComponentModel.Container components = null;
      private ConnectionPool pool;
      private UploadQueue queue;
      private long folderId;
      public Explorer()
        // Required for Windows Form Designer support
        InitializeComponent();
        // TODO: Add any constructor code after InitializeComponent call
         statusBox.Items.Add("Creating connection pool ...");
        pool = new ConnectionPool("http://content1.au.oracle.com:7777/content/ws", "matt", "welcome1", 5, 10);
        pool.setDebug(new System.IO.StreamWriter(Console.OpenStandardOutput()));
        statusBox.Items.Add("Attempting to obtainin session from pool ...");
        ManagersFactory session = pool.getSession();
        if (session != null)
          statusBox.Items.Add("Obtained session.");
          FileManager fileM = session.getFileManager();
          string path = "/oracle/users/Users-M/matt/Private Documents";
          statusBox.Items.Add("Looking up Sandbox "+path+ " ...");
          Item sandbox = fileM.resolvePath(path, null);
          if (sandbox != null)
            folderId = sandbox.getId();
            statusBox.Items.Add("Sandbox located - id: "+folderId);
          else
            statusBox.Items.Add("Unable to locate sandbox - disabling upload box.");
            uploadBox.Enabled=false;
          statusBox.Items.Add("Releasing session back to pool.");
          pool.releaseSession(session);
        else
          statusBox.Items.Add("Unable to obtain session - disabling upload box.");
          uploadBox.Enabled=false;
        if (folderId > 1)
          int size = 5;
          statusBox.Items.Add("Creating UploadQueue with "+size+" threads");
          queue = new UploadQueue(pool, size);
      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      protected override void Dispose( bool disposing )
        if( disposing )
          if (components != null)
            components.Dispose();
        base.Dispose( disposing );
        queue.Dispose();
        pool.Dispose();
      private void InitializeComponent()
        uploadBox = new ListBox();
        statusBox = new ListBox();
        this.SuspendLayout();
        statusBox.Name = "statusBox";
        statusBox.Enabled = true;
        statusBox.Location = new System.Drawing.Point(0,30);
        statusBox.Size = new System.Drawing.Size(492, 75);
        statusBox.AllowDrop = false;
        statusBox.MultiColumn = false;
        statusBox.TabIndex = 1;
        uploadBox.Name = "uploadBox";
        uploadBox.Location = new System.Drawing.Point(0, 145);
        uploadBox.Size = new System.Drawing.Size(494, 95);
        uploadBox.AllowDrop = true;
        uploadBox.TabIndex = 2;
        uploadBox.DragDrop += new System.Windows.Forms.DragEventHandler(this.uploadBox_DragDrop);
        uploadBox.DragEnter += new System.Windows.Forms.DragEventHandler(this.uploadBox_DragEnter);
        this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
        this.ClientSize = new System.Drawing.Size(500, 250);
        this.Controls.Add(statusBox);
        this.Controls.Add(uploadBox);
        this.KeyPreview = true;
        this.Name = "Explorer";
        this.Text = "CDB Explorer";
        this.ResumeLayout(false);
      private void uploadBox_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
        if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
          e.Effect = DragDropEffects.Copy;
        else
          e.Effect = DragDropEffects.None;
      private void uploadBox_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        foreach (string fileName in (string[])e.Data.GetData(DataFormats.FileDrop) )
          uploadBox.Items.Add(fileName);
          UploadTask task = new UploadTask(this.folderId, fileName);
          queue.EnqueueTask(task);
      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
        Application.Run(new Explorer());
    }

  • Need Help to Draw and Drag Triangle - URGENT

    Hi everyone - I am developing various proofs of the pythagora's theorem
    and the following code draws a triangle on screen and the proof follows -
    but i need to know how to drag the triangle such tht 1 angle is always set to 90 degrees.
    i.e. i need to resize the triangle by dragging its vertex points by which the1 angle remains at 90 no matter what the size.
    The proof has got some graphics code hardcoded in it - i.e. LINES AND POLYGONS have been hardcoded
    i need to reconfigure that such that everytime the user increases the size of the triagnle and clicks on next it draws the lines and polygons in the correct area and place
    PLEASE HELP
    the code is as follows
    MAIN CLASS
    import java.awt.BorderLayout;
    import java.awt.Container;
    import java.awt.*;
    import java.awt.event.*;
    import java.text.*;
    import javax.swing.*;
    public class TestProof {
        TestControl control;          // the controls for the visual proof
        TestView view;          // the drawing area to display proof
        // called upon class creation
        public TestProof() {
            view = new TestView();
    view.setBackground(Color.WHITE);
            control = new TestControl(view);
            Frame f = new Frame("Pythagoras");
            f.add(view,"Center");
            f.add(control,"South");
            f.setSize(600,600);
            f.setBackground(Color.lightGray);
            f.addMouseMotionListener(
            new MouseMotionListener() { //anonymous inner class
                //handle mouse drag event
                public void mouseMoved(MouseEvent e) {
                    System.out.println("Mouse  " + e.getX() +","  + e.getY());
                public void mouseDragged(MouseEvent e) {
                    System.out.println("Draggg: x=" + e.getX() + "; y=" + e.getY());
            JMenu File = new JMenu("File");
            JMenuItem Exit = new JMenuItem("Exit");
            Exit.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    ExitActionPerformed(evt);
            JMenuBar menuBar = new JMenuBar();
            menuBar.add(File);
       File.add(Exit);
            f.add(menuBar,"North");
            f.show();
        private JMenuBar getMenuBar() {
            JMenu File = new JMenu("File");
            JMenuItem Exit = new JMenuItem("Exit");
            Exit.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    ExitActionPerformed(evt);
            JMenuBar menuBar = new JMenuBar();
            menuBar.add(File);
                 File.add(Exit);   
            return menuBar;
        private void ExitActionPerformed(java.awt.event.ActionEvent evt) {
            // TODO add your handling code here:
            System.exit(0);
        // for standalone use
        public static void main(String args[]) {
      TestProof TP = new TestProof();
    }Test VIEW
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.text.*;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    public class TestView extends Canvas {
        int TRANSLUCENT = 1;
        int sequence;          // sequencer that determines what should be drawn
        // notes matter
        int noteX = 100;     // note coordinates
        int noteY = 60;
        int fontSize = 11;     // font size
        int lineSpacing     // space between two consecutive lines
        = fontSize + 2;
        Font noteFaceFont;     // font used to display notes
        // objects matter
        Polygon tri;          // right-angled triangle with sides A, B, and C
        Polygon tri1;
        Polygon sqrA;          // square with side of length A
        Polygon sqrB;          // square with side of length B
        Polygon sqrC;          // square with side of length C
        Polygon parA;          // parallelogram of base A and height A
        Polygon parB;          // parallelogram of base B and height B
        Polygon poly1;
        Polygon poly2;
        Polygon poly3;
        Polygon poly4;
        Polygon poly5;
        Polygon poly6;
        int X0 = 350;          // coordinates of triangle
        int Y0 = 350;
        int A = 90;//60;          // triangle size
        int B = 120;//80;
        int C = 150;//100;
        //CORDS of 2nd triangle
        int X1 = 350;
        int Y1 = 500;
        // notes: three lines per note
        String notes[] = {
            // note 0
            // note 1
            // note 2
            // note 3
            // note 4
            // note 5
            // note 6
            // note 7
            // note 8
            // note 9
            // note 10
            // note 11
            // note 12
            // note 13
            // note 14
        // constructor
        public TestView() {
            addMouseMotionListener(
            new MouseMotionListener() { //anonymous inner class
                //handle mouse drag event
                public void mouseMoved(MouseEvent e) {
                    System.out.println("Mouse  " + e.getX() +","  + e.getY());
                public void mouseDragged(MouseEvent e) {
                    System.out.println("Draggg: x=" + e.getX() + "; y=" + e.getY());
            // set font
            noteFaceFont = new Font("TimesRoman", Font.PLAIN, fontSize);
            // (coordinates specified w.r.t. to P0, unless otherwise specified)
            // create the triangle
            tri = new Polygon();
            tri.addPoint(0, 0);                    // add P0 coordinate
            tri.addPoint(A*A/C, -A*B/C);          // add A3 coordinate
            tri.addPoint(C, 0);                    // add C1 coordinate
            tri.translate(X0, Y0);               // place triangle
            tri1 = new Polygon();
            tri1.addPoint(0,0);                    // add P0 coordinate
            tri1.addPoint(A*A/C +38, +A*B/C);          // add A3 coordinate
            tri1.addPoint(C, 0);                    // add C1 coordinate
            tri1.translate(X1, Y1);
            // create square of side A
            sqrA = new Polygon();
            sqrA.addPoint(0, 0);               // add P0 coordinate
            sqrA.addPoint(-A*B/C, -A*A/C);          // add A1 coordinate
            sqrA.addPoint(-A*(B-A)/C, -A*(A+B)/C);     // add A2 coordinate
            sqrA.addPoint(A*A/C, -A*B/C);          // add A3 coordinate
            sqrA.translate(X0, Y0);               // place square
            // create square of side B
            // warning: the coordinate of this object are specified relative to C1
            sqrB = new Polygon();
            sqrB.addPoint(0, 0);               // add C1 coordinate
            sqrB.addPoint(B*A/C, -B*B/C);          // add B1 coordinate
            sqrB.addPoint(B*(A-B)/C, -B*(A+B)/C);     // add B2 coordinate
            sqrB.addPoint(-B*B/C, -B*A/C);          // add A3 coordinate
            sqrB.translate(X0 + C, Y0);               // place square
            // create square of side C
            sqrC = new Polygon();
            sqrC.addPoint(0, 0);               // add P0 coordinate
            sqrC.addPoint(C, 0);               // add C1 coordinate
            sqrC.addPoint(C, C);               // add C2 coordinate
            sqrC.addPoint(0, C);               // add C3 coordinate
            sqrC.translate(X0, Y0);               // place square
            poly1 = new Polygon();
            poly1.addPoint(405,279);
            poly1.addPoint(413,350);
            poly1.addPoint(432,500);
            poly1.addPoint(442,571);
            poly1.addPoint(500,500);
            poly1.addPoint(500,350);
            poly2 = new Polygon();
            poly2.addPoint(279,297);
            poly2.addPoint(404,280);
            poly2.addPoint(571,254);
            poly2.addPoint(500,350);
            poly2.addPoint(350,350);
            //Polygon 3
            poly3 = new Polygon();
            poly3.addPoint(404,280);
            poly3.addPoint(350,350);
            poly3.addPoint(414,350);
            poly4 = new Polygon();
            poly4.addPoint(350,350);
            poly4.addPoint(350,500);
            poly4.addPoint(442,572);
            poly4.addPoint(433,500);
            poly4.addPoint(414,350);
            poly5 = new Polygon();
            poly5.addPoint(476,183);
            poly5.addPoint(332,225);
            poly5.addPoint(278,295);
            poly5.addPoint(404,279);
            poly5.addPoint(571,254);
            poly6= new Polygon();
            poly6.addPoint(405,278);
            poly6.addPoint(332,224);
            poly6.addPoint(476,182);
            // create parallelogram of height A
            parA = new Polygon();
            parA.addPoint(0, 0);               // add P0 coordinate
            parA.addPoint(0, C);               // add C3 coordinate
            parA.addPoint(A*A/C, C - A*B/C);          // add Q0 coordinate
            parA.addPoint(A*A/C, -A*B/C);          // add A3 coordinate
            parA.translate(X0,Y0);               // place parallelogram
            // create parallelogram of height B
            // warning: the coordinate of this object are specified from C1
            parB = new Polygon();
            parB.addPoint(0, 0);               // add C1 coordinate
            parB.addPoint(-B*B/C, -B*A/C);          // add A3 coordinate
            parB.addPoint(A*A/C - C, C - A*B/C);     // add Q0 coordinate
            parB.addPoint(0, C);               // add C2 coordinate
            parB.translate(X0 + C, Y0);
            // place parallelogram
        // depending on the sequence number we draw certain objects
        public void paint(Graphics gfx) {
            super.paint(gfx);
            Graphics2D g = (Graphics2D) gfx;
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
            // text first, then objects (and animation)
            // we always output some notes
            g.drawString(notes[3*sequence], noteX, noteY);
            g.drawString(notes[3*sequence + 1], noteX, noteY + lineSpacing);
            g.drawString(notes[3*sequence + 2], noteX, noteY + 2*lineSpacing);
            // the object are drawn in an order so that they are properly overlapped
            if(sequence == 13) {
                g.setColor(Color.green);
                g.fillPolygon(poly1);
                g.fillPolygon(poly2);
                g.fillPolygon(poly3);
                g.fillPolygon(poly4);
                g.fillPolygon(poly5);
                g.setColor(Color.RED);
                g.setColor(Color.GREEN);
                g.drawLine(413,351,433,499);
                g.setColor(Color.white);
                g.fillPolygon(tri);
                g.fillPolygon(tri1);
                g.fillPolygon(poly6);
            if(sequence == 12 ) {
                g.setColor(Color.green);
                g.fillPolygon(poly1);
                g.fillPolygon(poly2);
                g.fillPolygon(poly3);
                g.fillPolygon(poly4);
                g.fillPolygon(poly5);
                g.setColor(Color.BLACK);
            if(sequence == 11){
                g.setColor(Color.green);
                g.fillPolygon(poly1);
                g.fillPolygon(poly3);
                g.fillPolygon(poly4);
                g.setColor(Color.BLACK);
            if(sequence == 8 ){
                g.setColor(Color.green);
                g.fillPolygon(poly5);
                g.setColor(Color.MAGENTA);
                g.drawString("E",578,254);
                g.drawString("D",268,302);
                g.setColor(Color.black);
                g.drawArc(250,150,350,250,320,65);
            else if (sequence == 9 ){
                g.setColor(Color.green);
                g.fillPolygon(poly2);
                g.setColor(Color.MAGENTA);
                g.drawString("E",578,254);
                g.drawString("D",268,302);
                g.setColor(Color.black);
                g.drawArc(250,150,350,250,320,65);
            if( sequence == 10){
                g.setColor(Color.green);
                g.fillPolygon(poly2);
                g.fillPolygon(poly5);
                g.setColor(Color.black);
                g.setColor(Color.MAGENTA);
                g.drawString("E",578,254);
                g.drawString("D",268,302);
                g.setColor(Color.black);
                g.drawArc(250,150,350,250,320,65);
            if(sequence == 7){
                g.setColor(Color.green);
                g.fillPolygon(poly2);
                g.setColor(Color.MAGENTA);
                g.drawString("E",578,254);
                g.drawString("D",268,302);
                g.setColor(Color.black);
            if(sequence == 6){
                g.setColor(Color.yellow);
                g.fillPolygon(poly2);
                g.setColor(Color.green);
                g.fillPolygon(poly3);
                g.setColor(Color.blue);
                g.fillPolygon(poly4);
                g.setColor(Color.black);
                g.drawArc(250,175,350,275,300,65);
                //g.drawArc(250,150,350,250,320,65);
                g.drawLine( 606,309,599,299);
                g.drawLine(592,313, 599,299);
                g.drawString("+90 degrees",605,378);
            if (sequence == 5 ) {
                g.setColor(Color.yellow);
                g.fillPolygon(poly2);
                g.setColor(Color.black);
            if (sequence == 4) {
                g.setColor(Color.YELLOW);
                g.fillPolygon(poly1);
                g.setColor(Color.black);
                g.drawArc(319,310,250,195,89,-35);
                g.drawLine(499,319, 492,312);
                g.drawLine(499,319, 492,325);
                g.drawArc(200,180, 233,238,-120,-60);
                g.drawLine(200,298, 208,309);
                g.drawLine(200,298, 194,313);
                g.drawString("-90 degrees",227,347);
            if (sequence >= 3) {
                g.drawLine(404,279,442,572);
            // draw the squares
            if (sequence >= 2) {
                g.drawLine(278,296,572,254);
            // draw the squares
            if (sequence >= 1) {
                g.drawLine(333,224,476,182);
                g.drawPolygon(tri1);
            // always draw the triangle
            g.drawPolygon(tri);
            g.drawPolygon(sqrA);
            g.drawPolygon(sqrB);
            g.drawPolygon(sqrC);
            g.setColor(Color.MAGENTA);
            g.drawString("C", X0 + C/2 - fontSize/2, Y0 + lineSpacing);
            g.drawString("A",
            X0 + A*A/(2*C) - fontSize*A/B/2,
            Y0 - A*B/(2*C) - lineSpacing*A/B);
            g.drawString("B",
            X0 + C - B*B/(2*C) - fontSize*A/B/2,// the last "-" isn't log.
            Y0 - B*A/(2*C) - lineSpacing*A/B);
        public void redraw(int sequence) {
            this.sequence = sequence;
            repaint();
    }TEST CONTROL
    * TestControl.java
    * Created on 28 February 2005, 11:16
    import java.awt.*;
    import java.awt.event.*;
    import java.text.*;
    import javax.swing.JFrame;
    * @author  Kripa Bhojwani
    public class TestControl extends Panel implements ActionListener {
      TestView view;
      int sequence;                    // event sequence
      // constructor
      public TestControl(TestView view) {
        Button b = null;
        Label label = new Label("A^2 ");
        this.view = view;          // initialize drawble area
        sequence = 0;               // initialize sequence
        b = new Button("Prev");
        b.addActionListener(this);
        add(b);
        b = new Button("Next");
        b.addActionListener(this);
        add(b);
        add(label);
      // exported method
      public void actionPerformed(ActionEvent ev) {
        String label = ev.getActionCommand();
        if (label.equals("Prev")) {
          if (sequence >0) {
         --sequence;
        else {
          if (sequence < 15) {
         ++sequence;
        this.setEnabled(false);          // disable the controls
        view.redraw(sequence);
        this.setEnabled(true);          // enable the controls
    }Please help --- really need to sort this out...
    THANKS

    One of the problems you face is that it is hard to recognise which parts of your code are drawing the triangle. This is because you are writing code in a procedural way rather than an object oriented way.
    In object oriented code you would have a triangle object that could draw itself. You would create the triangle object by specifying its sizes and angles in some way. Then it should be easy to change the triangles sizes and angles and ask all the drawn objects to redraw themselves.

  • Possibility of drawing numbers on java bouncing balls?

    Can anyone show me how to put numbers on these moving balls in my code. I need the numbers 1-60 on them. I have two sets the red and white. Here is my code. Any help is appreciated. I am trying to write a program to represent the powerball.
    import java.awt.*;
    import java.applet.*;
    import java.util.*;
    import javax.swing.*;
    import java.awt.Rectangle;
    class CollideBall{
    int width, height;
    public static final int diameter=20;
    //coordinates and value of increment
    double x, y, xinc, yinc, coll_x, coll_y;
    boolean collide;
    Color color;
    Graphics g;
    Rectangle r;
    //the constructor
    public CollideBall(int w, int h, int x, int y, double xinc, double yinc, Color c){
    width=w;
    height=h;
    this.x=x;
    this.y=y;
    this.xinc=xinc;
    this.yinc=yinc;
    color=c;
    r=new Rectangle(150,80,130,90);
    public double getCenterX() {return x+diameter/2;}
    public double getCenterY() {return y+diameter/2;}
    public void alterRect(int x, int y, int w, int h){
    r.setLocation(x,y);
    r.setSize(w,h);
    public void move(){
    if (collide){  
    double xvect=coll_x-getCenterX();
    double yvect=coll_y-getCenterY();
    if((xinc>0 && xvect>0) || (xinc<0 && xvect<0))
    xinc=-xinc;
    if((yinc>0 && yvect>0) || (yinc<0 && yvect<0))
    yinc=-yinc;
    collide=false;
    x+=xinc;
    y+=yinc;
    //when the ball bumps against a boundary, it bounces off
    //ball width is 6 so if the ball becomes less then 6 it is touching the frame
    //if ball is greater than the entire width-the diameter of the rectangle, then the ball is just touching the frame of the rectangle and must switch to negative to go in opposit direction
    if(x<6 || x>width-diameter){
    xinc=-xinc;
    x+=xinc;
    //same thing as about just about the Y-axis instead of the x-axis
    if(y<6 || y>height-diameter){
    yinc=-yinc;
    y+=yinc;
    public void hit(CollideBall b){
    if(!collide){
    coll_x=b.getCenterX();
    coll_y=b.getCenterY();
    collide=true;
    public void paint(Graphics gr){
    g=gr;
    g.setColor(color);
    //the coordinates in fillOval have to be int, so we cast
    //explicitly from double to int
    g.fillOval((int)x,(int)y,diameter,diameter);
    //Draws half white and half dark gray arc around the balls to give light and shadow effect
    g.setColor(Color.white);
    g.drawArc((int)x,(int)y,diameter,diameter,45,180);
    g.setColor(Color.darkGray);
    g.drawArc((int)x,(int)y,diameter,diameter,225,180);
    public class BouncingBalls extends Applet implements Runnable { 
    Thread runner;
    Image Buffer;
    Graphics gBuffer;
    CollideBall ball[];
    //Obstacle o;
    //how many balls?
    static final int MAX=60;
    boolean intro=true,drag,shiftW,shiftN,shiftE,shiftS;
    boolean shiftNW,shiftSW,shiftNE,shiftSE;
    int xtemp,ytemp,startx,starty;
    int west, north, east, south;
    public void init() {  
    Buffer=createImage(getSize().width,getSize().height);
    gBuffer=Buffer.getGraphics();
    ball=new CollideBall[MAX];
    int w=getSize().width-5;
    int h=getSize().height-5;
    //our balls have different start coordinates, increment values
    //(speed, direction) and colors
    for (int i = 0;i<30;i++){
    ball=new CollideBall(w,h,48+i,500+i,1.5,2.0,Color.white);
    ball[i+30]=new CollideBall(w,h,890+i,200+i,1.5,2.0,Color.red);
    public void start(){
    if (runner == null) {
    runner = new Thread (this);
    runner.start();
    /* public void stop(){
    if (runner != null) {
    runner.stop();
    runner = null;
    public void run(){
    while(true) {
    Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    try {runner.sleep(15);}
    catch (Exception e) { }
    //move our balls around
    for(int i=0;i<MAX;i++){
    ball[i].move();
    handleCollision();
    repaint();
    boolean collide(CollideBall b1, CollideBall b2){
    double wx=b1.getCenterX()-b2.getCenterX();
    double wy=b1.getCenterY()-b2.getCenterY();
    //we calculate the distance between the centers two
    //colliding balls (theorem of Pythagoras)
    double distance=Math.sqrt(wx*wx+wy*wy);
    if(distance<b1.diameter)
    return true;
    return false;
    private void handleCollision(){
    //we iterate through all the balls, checking for collision
    for(int i=0;i<MAX;i++)
    for(int j=0;j<MAX;j++){
    if(i!=j){         
    if(collide(ball[i], ball[j])){  
    ball[i].hit(ball[j]);
    ball[j].hit(ball[i]);
    public void update(Graphics g){
    paint(g);
    public void paint(Graphics g) { 
    gBuffer.setColor(Color.lightGray);
    gBuffer.fillRect(0,0,getSize().width,getSize().height);
    gBuffer.draw3DRect(5,5,getSize().width-10,getSize().height-10,false);
    //paint our balls
    for(int i=0;i<MAX;i++)
    ball[i].paint(gBuffer);
    g.drawImage (Buffer,0,0, this);
    Thanks again

    this.user wrote:
    JakeG27 post your code within the code tab it will be more clear.
    You can do this by clicking on CODE when you do this will appear { code} { code} post your code inbetween those to tags.
    ie
    { code} code... { code}
    and it will look like this
    code
    This must be the first sensible post you've ever made. At least you're able to copy someone else's response and pretend you know something.

  • Alarm status drawing iow: recolour JInternalFrame components

    Greetings,
    Please have a look at this picture. It's a low res snapshot of
    a few quite complicated components. Most of the functionality isn't
    visible nor relevant in the example. What you're looking at is a real time
    process of some sort. Things can go wrong in that process. In a previous
    version of my views I'd turn the background colour of some components
    red/yellow/green according to the 'alarm status' of the process. One of
    my customers suggested the idea of turning everything red/yellow/green
    inside those JInternalFrames (that's what you're looking at in the example).
    Of course one fool can ask more than a dozen of wise men can answer
    and I am not that wise, so my question is: how would one change the
    colour of all components that are part of a JInternalFrame (or any
    other container) such that the colour wouldn't be 100% opague but
    still visible by itself and still showing the information originally present
    in each individual component. iow, as if a transparent monochrome
    filter were positioned in front of that entire JContainer.
    In a naive way I like the idea; if the idea turns out to be too complicated
    to realize I'd be happy with visual alternatives also. (such as big arrows
    pointing to the JContainer where the alarm happened).
    Note that these appliations run in a 'factory' environment where people
    either hardly watch the screens or they watch them at quite a great
    distance. The changing colours should just attract their attention so they
    will walk/run/drive/ride to the screens for a second inspection.
    Any ideas are appreciated.
    kind regards,
    Jos

    Not sure I understand the question, but I keyed in on:
    as if a transparent monochrome filter were positioned in front of that entire JContainer.So maybe you could use a GlassPane:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    public class GlassPaneTest extends JFrame
        public GlassPaneTest()
            final JComponent glassPane = new JComponent()
                public void paintComponent(Graphics g)
                    g.setColor( getBackground() );
                    g.fillRect(0, 0, getSize().width, getSize().height);
            glassPane.setOpaque( false );
            glassPane.setBackground( new Color(240, 20, 20, 100) );
            setGlassPane( glassPane );
            glassPane.addKeyListener( new KeyAdapter()
                public void keyPressed(KeyEvent e)
                    e.consume();
            glassPane.addMouseListener( new MouseAdapter()
                public void mousePressed(MouseEvent e)
                    e.consume();
            final JButton button = new JButton( "Click Me" );
            button.setMnemonic('c');
            button.addActionListener( new ActionListener()
                public void actionPerformed(ActionEvent e)
                       glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                       glassPane.setVisible( true );
                       glassPane.requestFocus();
                       Thread thread = new Thread()
                            public void run()
                                try { this.sleep(5000); }
                                catch (InterruptedException ie) {}
                                 glassPane.setVisible( false );
                                 glassPane.setCursor(null);
                    thread.start();
            getContentPane().add(new JLabel("NORTH"), BorderLayout.NORTH );
            getContentPane().add( button );
            getContentPane().add(new JTextField(), BorderLayout.SOUTH);
        public static void main(String[] args)
            GlassPaneTest frame = new GlassPaneTest();
            frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
            frame.setSize(300, 300);
            frame.setLocationRelativeTo( null );
            frame.setVisible(true);
    }The Swing tutorial on [url http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html]How to Use Glass Panes shows how you can also do a simple drawing (your arrow?) on the glass pane.

  • Looking for a high-res drawing app for the iPad

    I've tried a few of the available iPad drawing apps like Sketchbook Pro and Brushes. It's a little hard to tell, because documentation tends to be short on details, but it appears that most of them (with the exception of Brushes) only let you work and export images at 1024 by 768 resolution. That isn't really high enough resolution for professional work.
    Brushes is the only exception I've found. You work on the iPad in Brushes at 1024 by 768, but they have this OS X app that can convert your exported images to a higher res.
    To me that's crazy awkward and time-consuming, and I think Brushes is OK as a drawing app, but not necessarily what I'm looking for.
    Can anyone give me some better insight into the matter?
    Is there some underlying technical reason that all of these apps have a hard limit of 1024 by 768 resolution?
    Is there an app other than Brushes that can produce pro-level (high resolution) image files on the iPad?
    Thanks,
    JS

    Yubz Magnum really has great sound. They come in four colors too.
    Check out the new remodeled MacOSG website! 24-hour Apple-related news & support.
     MacOSG: An Apple User Group  iTunes: MacOSG Podcast  Follow us on Twitter: MacOSG

  • CS5 or Elements for Drawing?

    hello everyone. I know this doesn't sound original but I have yet to find an answer so I came here. I am hoping to get a Wacom Bamboo Fun tablet soon and it includes Adobe Elements 8. I am an artist and browsing around places like DeviantArt i find that most digital artists use the program CS5 or something like that. So here's my question: is CS5 or Elements better for drawing? I'm seriously thinking about getting CS5 but i don't want to waste my money if Elements is just as good. Please help me out!!

    Elements is more limited in how to adjust the colors to black-and-white.
    Lightroom has more sophisticated adjustments.  These adjustments are the same as in the Camera Raw plug-in for Photoshop, but absent in the Camera Raw plug-in for Elements.  The adjustments allow you to enhance the contrast and brightness of the gray-level for narrow ranges of original colors instead of a simple removal of color with a default color-balance or clicking on a preset that Elements has.
    Here is a very verbose video introduction to the LR B/W conversion on an example photo, viewed best in full-screen HD:
    http://www.luminous-landscape.com/tutorials/bw_workflow_in_lightroom.shtml
    Here is a step-by-step example with screenshots and description, from 2008, but the adjustments still mostly apply, except the vignetting you’d use wouldn’t be lens-related, it’d be the Post-Crop Vignetting in the Effects section that didn’t exist back in 2008:
    http://layersmagazine.com/create-stunning-black-and-white-images-in-lightroom.html
    These were just the first and third links that showed up after Googling for Lightroom Black and White.
    BTW, I am a photo-hobbyist and use Lightroom every day, so it’s not just for professionals making money off their photos that need something fast.  For me it is more about seriousness and perfection and freedom.

  • Error message (Because a USB device was drawing too much power)

    Hi Everyone,
    Bought recently a new macbook pro 13 inch with Retina display with 120 GB flash drive.
    Connected a non-apple CD drive to my macbook and after that started receiving this message: "Because a USB device was drawing too much power from your computer, one or more of your USB devices have been disabled."
    initially I was receiving this message after I switch on my macbook but now after every 30 seconds this message pops up although I never connected anything to my macbook through its USB ports.
    Will highly appreciate for your help on how to get rid of this problem.
    Regards
    Homayun

    Try resetting the SMC
    Shut down the computer.
    Plug in the MagSafe power adapter to a power source, connecting it to the Mac if its not already connected.
    On the built-in keyboard, press the (left side) Shift-Control-Option keys and the power button at the same time.
    Release all the keys and the power button at the same time.
    Press the power button to turn on the computer. 
    Note: The LED on the MagSafe power adapter may change states or temporarily turn off when you reset the SMC.

  • When I try to print a drawing imported from my ipad iphoto crops it. Is there any way to stop this?

    When I try to print a drawing imported from my ipad iphoto crops it. Is there any way to stop this?

    Usual cause: printing at the wrong aspect ratio for the image - trying to print 5 x 3 in the shape of a 6 x 4 for instance.
    Regards
    TD

  • Draw back of Automatic PO creation

    Dear Friends,
    What are all the draw backs will come if i cxreate PO automatically once GR posted.
    Kindly explain me.
    Rgds,
    Sankar.D

    Prerequisits.
    a) Movement type has to be selected for automatic creation of PO in customizing (IM - GR - Create PO automatically)
    b)Assign Std. Purchasing Org. to plant (Enterprise structure - Assignment - MM)
    c)Define default values for PO document type depending on T-Code MB01
    d)Material should be valuated material with material master
    e)Valid price should be there in Purchasing Info. record.
    There are no drawbacks as such , but you can only procure valuated materials, PO of consumable materials is ruled out .
    Check the possibilities and let us know what is your specific requirement.
    Regards

  • Photoshop CC: When I'm trying to draw a rectangle I can't fill it or create a stoke because there is a message telling me; "Could not complete your request because of a program error. What can I do?

    Photoshop CC: When I'm trying to draw a rectangle I can't fill it or create a stoke because there is a message telling me; "Could not complete your request because of a program error. What can I do?

    It is a mute point now. PSE12 finally failed to the point it locked up the MAC. I had to restore the MAC OS from backup to a point before the PSE12 update.
    The MAC now operates correctly and so does PSE12. I don't think I'll be updating PSE any time soon.

  • Can not use all the tools in my drawing markups any ideas on getting them to work?

    Can not use all the tools in my drawing markups any ideas on getting them to work?

    Hi tonys60181,
    Could you please let me know what version of Adobe Acrobat are you using.
    What all drawing tools are you unable to access?
    Is this issue specific to one PDF file or all?
    What exactly happens when you try to use any drawing markup?
    Please let me know.
    Regards,
    Anubha

  • I am trying to upload photos from my digital camera. Every time I try to plug it into my USB, the following error message comes up: "Because a usb device was drawing too much power from your computer, one or more of your USB devices have been disabled."

    I am trying to upload photos from my digital camera. Every time I try to plug it into my USB, the following error message comes up: "Because a usb device was drawing too much power from your computer, one or more of your USB devices have been disabled."
    I don't have anything else plugged into my MBP, so I am confused as to what's going on.  This problem has never happened before.  MBP is less than a year old - about 9 months old.  HELP

    Get a powered USB hub.
    https://discussions.apple.com/community/notebooks/macbook_pro?view=documents

Maybe you are looking for