0

I've been writing Java SE 8 desktop application. I use Eclipse IDE, Oracle's JDK, and run it on MS Windows 10 OS.

My app draws diagrams, in short. I draw a diagram on JPanel which becomes part of JTabbedPane. It displays it well on GUI, and it is very responsive. The problem shows up when I pass the diagram on printing service. But instead of printing it on printer, I choose, "Microsoft print to PDF" service. What happens next, is that if the diagram is large, when you scroll it down, you will observe that its quality drops down. That is, grids start disappearing, new lines appear, etc.

The pic out here. enter image description here

As you can see, eventually vertical grids vanish, diagonal line creeps in, and later gets even worse. And that is unwelcome.

Relevant code in here:

public final class GanttChartDiagram extends TopDiagram{
@Override  
    public void paintComponent(Graphics graph){
        super.paintComponent(graph);

        Graphics2D g2D = (Graphics2D)graph; 

        g2D.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
...........

@Override
    public Dimension getPreferredSize(){
        return new Dimension(this.diagramWidth + 20, this.diagramHeight + 20);
    }
}
}

The getPreferredSize() method identifies the size of diagram, so that the app knows how to adjust the scroll-bars accordingly to fit the diagram in. Otherwise by default it return 0, if not overridden. That is the class where I draw the diagram.

The super-class out here:

public abstract class TopDiagram extends JPanel implements Printable {
    private static final long serialVersionUID = 1469816888488484L;

    @Override
    public void paintComponent(Graphics graph){
        super.paintComponent(graph);
    };

    /**
     * Prints selected diagram
     */
    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {

        Graphics2D dimension = (Graphics2D)graphics;
        dimension.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

        if(pageIndex < PrintingImageBuffer.getImageBuffer().size()){
           dimension.drawImage(PrintingImageBuffer.getImageBuffer().get(pageIndex), null, 0, 0);
           return PAGE_EXISTS;
        }
        else{
            return NO_SUCH_PAGE;
        }               
    }   
}

Now that is where I print the diagram:

 public static void printDiagram(){
     new Thread(new Runnable(){

    public void run(){

    TopDiagram diagram = null;
                    if(id.equalsIgnoreCase("GanttChart")){
                        diagram = ganttChartDiagram;
    }

        final PrinterJob printer = PrinterJob.getPrinte

rJob();
                        printer.setJobName("Printing the "+id+" Diagram");  
                        PageFormat format = printer.pageDialog(page);

                        int nowWidth = (int)diagram.getPreferredSize().getWidth();
                        int nowHeight = (int)diagram.getPreferredSize().getHeight();

                        BufferedImage buffImg = new BufferedImage(nowWidth, nowHeight, BufferedImage.TYPE_INT_ARGB);//default type

                        Graphics2D d = (Graphics2D)buffImg.getGraphics();

    ....etc..................
    }

    }).start();
    }

Now the interesting part is this:

int nowWidth = (int)diagram.getPreferredSize().getWidth();
                        int nowHeight = (int)diagram.getPreferredSize().getHeight();

On the same instance of diagram, on multiple invocations of print (or within the method), it may or may not return different values. So that it was causing me some sort of Raster exception. But I managed to get rid off of that exception by invoking size method only once and reusing that size value throughout the method. So that, the size value stays the same, cause it is read only once. Bad solution, but it works.

I would like to solve this issue too. Firstly, how come that this invocation diagram.getPreferredSize().getWidth() on the same instance of diagram obj. returns different size value? One more thing, is that I overrode this method as has been presented above. And the diagram object is created only once, no recalculations.

This is where I create the diagram obj. on Swing Worker only once per application's life-cycle.

GanttChartSwingWorker ganttSwingWorker = new GanttChartSwingWorker(GanttChartDiagram::new, tabbedPane, showPerformanceDiagramTab, ganttChartDiagramTabReady);
        ganttSwingWorker.execute();

        new Thread(() -> {      
            try{
                ganttChartDiagramTabReady.await();              
                ganttChartDiagram = ganttSwingWorker.getGanttChartDiagram();                

            }catch(InterruptedException ie){ie.printStackTrace();}
        }
        ).start();

Swing Worker part:

diagram = this.get();

              JScrollPane scrollPaneChart = addScrollPane(diagram);              
              tabbedPane.addTab("Gantt Chart", null, scrollPaneChart, "Displays Gantt Chart Diagram");

Some diagram objects can be time consuming to create, imposes delay, so I use Swing Worker to do that.

So, in summary:

  1. How to make the diagram to appear clean when I print/save it on pdf file in the way that I explained?
  2. How to make the diagram size to calculate consistently as per multiple invocations? What leads to different diagram size values retrieving it from the same diagram object instance on multiple calls?
ucas
  • 417
  • 1
  • 11
  • 30

1 Answers1

0

I just figured out what the problem is.

I observed that when it comes to drawing the diagram, the paintComponent(Graphics g) method has been invoked repeatedly. It keeps redrawing the diagram over and over again. It is invoked by the system implicitly, yet my implementation had been triggering it.

And that trigger comes in the form of this.setSize(width, height) method on derived JPanel object. So that each time the paintComponent(Graphics g) re-executes, it sets the size on JPanel which yet triggers additional execution of the painComponent method. In the end, it is an infinite loop.

And that infinite execution was the cause of the problem; it was producing distorted diagram image on pdf file.

Solution: execute the setSize method only when it is needed; on initial panel set-up, or resize.

ucas
  • 417
  • 1
  • 11
  • 30