List of usage examples for java.awt Graphics drawString
public abstract void drawString(AttributedCharacterIterator iterator, int x, int y);
From source file:VASSAL.build.module.map.LOS_Thread.java
/** * Writes text showing the range//from w w w . j av a2 s .c o m * * @param range the range to display, in whatever units returned * by the {@link MapGrid} containing the thread */ public void drawRange(Graphics g, int range) { Point mapArrow = map.componentCoordinates(arrow); Point mapAnchor = map.componentCoordinates(anchor); g.setColor(Color.black); g.setFont(RANGE_FONT); final FontMetrics fm = g.getFontMetrics(); final StringBuilder buffer = new StringBuilder(); int dummy = range; while (dummy >= 1) { dummy = dummy / 10; buffer.append("8"); } if (buffer.length() == 0) { buffer.append("8"); } String rangeMess = Resources.getString("LOS_Thread.range"); int wid = fm.stringWidth(" " + rangeMess + " " + buffer.toString()); int hgt = fm.getAscent() + 2; int w = mapArrow.x - mapAnchor.x; int h = mapArrow.y - mapAnchor.y; int x0 = mapArrow.x + (int) ((wid / 2 + 20) * w / Math.sqrt(w * w + h * h)); int y0 = mapArrow.y + (int) ((hgt / 2 + 20) * h / Math.sqrt(w * w + h * h)); g.fillRect(x0 - wid / 2, y0 + hgt / 2 - fm.getAscent(), wid, hgt); g.setColor(Color.white); g.drawString(rangeMess + " " + range, x0 - wid / 2 + fm.stringWidth(" "), y0 + hgt / 2); lastRangeRect = new Rectangle(x0 - wid / 2, y0 + hgt / 2 - fm.getAscent(), wid + 1, hgt + 1); Point np = map.mapCoordinates(new Point(lastRangeRect.x, lastRangeRect.y)); lastRangeRect.x = np.x; lastRangeRect.y = np.y; lastRange = String.valueOf(range); }
From source file:thesaurusEditor.gui.graph.MainGraph.java
/** * create an instance of a simple graph with basic controls *//*from w ww. j a v a 2s. c o m*/ public MainGraph(List<Konzept> konzepte, Main main) { // create a simple graph for the demo this.konzepte = konzepte; this.main = main; main.getController().getThesaurus().addObserver(this); graph = new DirectedSparseGraph<Konzept, EdgeClass>(); for (Konzept k : konzepte) { graph.addVertex(k); } createEdges(konzepte); layout = new PersistentLayoutImpl<Konzept, EdgeClass>(new FRLayout<Konzept, EdgeClass>(graph)); //layout = new FRLayout<Konzept,EdgeClass>(graph); Dimension preferredSize = new Dimension(1300, 900); final VisualizationModel<Konzept, EdgeClass> visualizationModel = new DefaultVisualizationModel<Konzept, EdgeClass>( layout, preferredSize); vv = new VisualizationViewer<Konzept, EdgeClass>(visualizationModel, preferredSize); // this class will provide both label drawing and vertex shapes VertexLabelAsShapeRenderer<Konzept, EdgeClass> vlasr = new VertexLabelAsShapeRenderer<Konzept, EdgeClass>( vv.getRenderContext()); // customize the render context vv.getRenderContext().setVertexLabelTransformer(new Transformer<Konzept, String>() { public String transform(Konzept k) { return ""; } }); // this chains together Transformers so that the html tags // are prepended to the toString method output /*new ChainedTransformer<Konzept,String>(new Transformer[]{ new ToStringLabeller<Konzept>(), new Transformer<Konzept,String>() { public String transform(Konzept input) { return input.toString(); }}}));*/ vv.getRenderContext().setVertexShapeTransformer(new Transformer<Konzept, Shape>() { public Shape transform(Konzept k) { return new Rectangle(-((k.toString().length() * 8 + 10) / 2), -(10), k.toString().length() * 7 + 18, 21); } }); vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.red)); vv.getRenderContext().setEdgeDrawPaintTransformer(new ConstantTransformer(Color.black)); vv.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(2.5f))); vv.getRenderContext().setVertexFillPaintTransformer( new PickableVertexPaintTransformer<Konzept>(vv.getPickedVertexState(), Color.white, Color.yellow)); vv.getRenderContext().setEdgeDrawPaintTransformer( new PickableEdgePaintTransformer<EdgeClass>(vv.getPickedEdgeState(), Color.black, Color.red)); vv.getRenderContext().setVertexIconTransformer(new Transformer<Konzept, Icon>() { /* * Implements the Icon interface to draw an Icon with background color and * a text label */ public Icon transform(final Konzept v) { return new Icon() { private Konzept k; public int getIconHeight() { return 20; } public int getIconWidth() { if (k != null) { return k.toString().length() * 7 + 10; } return v.toString().length() * 7 + 10; } public void paintIcon(Component c, Graphics g, int x, int y) { if (vv.getPickedVertexState().isPicked(v)) { g.setColor(Color.yellow); } else { g.setColor(Color.lightGray); } g.fillRect(x, y, v.toString().length() * 8 + 10, 20); if (vv.getPickedVertexState().isPicked(v)) { g.setColor(Color.black); } else { g.setColor(Color.black); } g.drawRect(x, y, v.toString().length() * 8 + 10, 20); if (vv.getPickedVertexState().isPicked(v)) { g.setColor(Color.black); } else { g.setColor(Color.black); } this.k = v; if (vv.getPickedVertexState().isPicked(v)) { Font font = new Font("DejaVu Sans Mono", Font.BOLD, 14); g.setFont(font); g.drawString("" + v, x + 6, y + 15); } else { Font font = new Font("DejaVu Sans Mono", Font.PLAIN, 14); g.setFont(font); g.drawString("" + v, x + 6, y + 15); } this.k = v; } }; } }); // customize the renderer /*GradientVertexRenderer<Konzept,EdgeClass> vertex = new GradientVertexRenderer<Konzept,EdgeClass>(Color.white, Color.white, true); vv.getRenderer().setVertexRenderer(vertex); vv.getRenderer().setVertexLabelRenderer(vlasr); */ vv.setBackground(Color.white); // add a listener for ToolTips KonzeptParser<Konzept> parser = new KonzeptParser<Konzept>(); vv.setVertexToolTipTransformer(parser); /*final DefaultModalGraphMouse<Konzept,Edge> graphMouse = new DefaultModalGraphMouse<Konzept,Edge>(); */ Factory<Konzept> vertexFactory = new VertexFactory(); Factory<EdgeClass> edgeFactory = new EdgeFactory(); graphMouse = new MyModalGraphMouse<Konzept, EdgeClass>(vv.getRenderContext(), vertexFactory, edgeFactory, main, vv); vv.setGraphMouse(graphMouse); vv.addKeyListener(graphMouse.getModeKeyListener()); // the EditingGraphMouse will pass mouse event coordinates to the // vertexLocations function to set the locations of the vertices as // they are created // graphMouse.setVertexLocations(vertexLocations); vv.setGraphMouse(graphMouse); vv.addKeyListener(graphMouse.getModeKeyListener()); graphMouse.setMode(ModalGraphMouse.Mode.EDITING); GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); JComboBox modeBox = graphMouse.getModeComboBox(); modeBox.addItemListener(graphMouse.getModeListener()); //graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); final ScalingControl scaler = new CrossoverScalingControl(); JButton plus = new JButton(); plus.setIcon(new ImageIcon(getClass().getResource("/thesaurusEditor/img/zoom_in.png"))); plus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { scaler.scale(vv, 1.1f, vv.getCenter()); } }); JButton minus = new JButton(); minus.setIcon(new ImageIcon(getClass().getResource("/thesaurusEditor/img/zoom_out.png"))); minus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { scaler.scale(vv, 1 / 1.1f, vv.getCenter()); } }); JPanel controls = new JPanel(); JPanel zoomControls = new JPanel(new GridLayout(1, 2)); //zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); zoomControls.add(plus); zoomControls.add(minus); controls.add(zoomControls); //controls.add(modeBox); /* javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(gzsp); gzsp.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 374, Short.MAX_VALUE) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 106, Short.MAX_VALUE) ); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(controls); controls.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 374, Short.MAX_VALUE) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 164, Short.MAX_VALUE) );*/ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(gzsp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(controls, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap())); layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup( javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup().addContainerGap() .addComponent(gzsp, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(controls, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap())); }
From source file:com.rapidminer.gui.plotter.charts.AbstractBarChartPlotter.java
public void paintBarChart(Graphics graphics) { int categoryCount = prepareData(); String groupByName = groupByColumn >= 0 ? dataTable.getColumnName(groupByColumn) : null; String valueName = valueColumn >= 0 ? dataTable.getColumnName(valueColumn) : null; String maxClassesProperty = System.getProperty(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_COLORS_CLASSLIMIT); int maxClasses = 20; try {// w w w . j ava 2s . c om if (maxClassesProperty != null) maxClasses = Integer.parseInt(maxClassesProperty); } catch (NumberFormatException e) { LogService.getGlobal().log( "Bar Chart plotter: cannot parse property 'rapidminer.gui.plotter.colors.classlimit', using maximal 20 different classes.", LogService.WARNING); } boolean createLegend = categoryCount > 0 && categoryCount < maxClasses; if (categoryCount <= MAX_CATEGORIES) { JFreeChart chart = createChart(categoryDataSet, groupByName, valueName, createLegend); // set the background color for the chart... chart.setBackgroundPaint(Color.white); // legend settings LegendTitle legend = chart.getLegend(); if (legend != null) { legend.setPosition(RectangleEdge.TOP); legend.setFrame(BlockBorder.NONE); legend.setHorizontalAlignment(HorizontalAlignment.LEFT); } Rectangle2D drawRect = new Rectangle2D.Double(0, 0, getWidth(), getHeight()); chart.draw((Graphics2D) graphics, drawRect); } else { graphics.drawString("Too many columns (" + categoryCount + "), this chart is only able to plot up to " + MAX_CATEGORIES + " different categories", MARGIN, MARGIN); } }
From source file:edu.ku.brc.af.ui.forms.validation.ValFormattedTextFieldSingle.java
@Override public void paint(Graphics g) { super.paint(g); String text = getText();/*from ww w . j a va 2 s . c o m*/ //System.err.println("isViewOnly "+isViewOnly+" isEnabled() "+isEnabled()+ " ["+text+"] "+(text.length() < bgStr.length())); if (!isViewOnly && needsUpdating && isEnabled() && text != null && text.length() < bgStr.length()) { FontMetrics fm = g.getFontMetrics(); int w = fm.stringWidth(text); pnt = new Point(inner.left + w, inner.top + fm.getAscent()); Rectangle r = g.getClipBounds(); Dimension s = getSize(); Insets i2 = getBorder().getBorderInsets(this); int x = i2.left - 1; int y = i2.top - 1; //int ww = s.width - i2.right + 1; int hh = s.height - i2.bottom + 1; String str = bgStr.substring(text.length(), bgStr.length()); int bgW = fm.stringWidth(str); g.setClip(x + w, y, Math.min(x + bgW, g.getClipBounds().width - x), hh); g.setColor(textColor); g.drawString(str, pnt.x, pnt.y); g.setClip(r.x, r.y, r.width, r.height); // reset clip } //System.out.println(hashCode() + " isNew: " +isNew+" valState: "+valState+" isEnabled: "+isEnabled()); // 3/2/09 - rods - removing !isNew from the condition //if (!isNew && valState == UIValidatable.ErrorType.Error && isEnabled()) if (valState == UIValidatable.ErrorType.Error && isEnabled()) { UIHelper.drawRoundedRect((Graphics2D) g, isNew ? new Color(249, 249, 0) : valTextColor.getColor(), getSize(), 1); } else if (valState == UIValidatable.ErrorType.Incomplete && isEnabled()) { UIHelper.drawRoundedRect((Graphics2D) g, new Color(249, 249, 0), getSize(), 1); } }
From source file:ru.spbspu.viewer.DataView.java
private void drawScaleFull() { int specHeigth = fullSpectrogram.getHeight() - cursor.getHeight() / 2; float limit = Integer.valueOf(spinnerLimitFreq.getValue().toString()); int frameWidth = Integer.valueOf(spinnerFrameWidth.getValue().toString()); BufferedImage scaleForFrame = new BufferedImage(SCALE_OF_SPECT, specHeigth, BufferedImage.TYPE_INT_RGB); Graphics g = scaleForFrame.getGraphics(); g.drawLine(5, 0, 5, specHeigth);// w w w.ja v a 2 s .c om Integer[] yAxis = new Integer[specHeigth / 8]; for (int i = 0; i < yAxis.length; i++) { yAxis[i] = (int) (i * (limit / 1024) * 100); } int j = 0; for (int i = specHeigth; i > 0; i -= specHeigth / 10) { g.drawString(yAxis[j].toString(), 7, i - 2); g.drawLine(0, i, 40, i); j++; } labelForFullScale.setIcon(new ImageIcon(scaleForFrame)); }
From source file:ru.spbspu.viewer.DataView.java
private void drawScale() { int specHeigth = spectrogram.getHeight() - cursor.getHeight() / 2; float limit = Integer.valueOf(spinnerLimitFreq.getValue().toString()); int frameWidth = Integer.valueOf(spinnerFrameWidth.getValue().toString()); BufferedImage scaleForFrame = new BufferedImage(SCALE_OF_SPECT, specHeigth, BufferedImage.TYPE_INT_RGB); Graphics g = scaleForFrame.getGraphics(); g.drawLine(5, 0, 5, specHeigth);/*from w w w .ja v a 2 s . c o m*/ Integer[] yAxis = new Integer[specHeigth / 8]; try { for (int i = 0; i < yAxis.length; i++) { yAxis[i] = (int) (i * (limit / 1024) * 100); } int j = 0; for (int i = specHeigth; i > 0; i -= specHeigth / 10) { g.drawString(yAxis[j].toString(), 7, i - 2); g.drawLine(0, i, 40, i); j++; } } catch (ArrayIndexOutOfBoundsException e) { System.out.println("To small window."); } labelForFrameScale.setIcon(new ImageIcon(scaleForFrame)); }
From source file:ded.ui.DiagramController.java
/** Check to see if the font is rendering properly. I have had a * lot of trouble getting this to work on a wide range of * machines and JVMs. If the font rendering does not work, just * alert the user to the problem but keep going. */ public void checkFontRendering() { // Render the glyph for 'A' in a box just large enough to // contain it when rendered properly. int width = 9; int height = 11; BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics g = bi.createGraphics(); ColorModel colorModel = bi.getColorModel(); g.setColor(Color.WHITE);/*from w w w. j av a2s . c om*/ g.fillRect(0, 0, width, height); g.setColor(Color.BLACK); g.setFont(this.dedWindow.diagramFont); g.drawString("A", 0, 10); // Print that glyph as a string. StringBuilder sb = new StringBuilder(); for (int y = 0; y < height; y++) { int bits = 0; for (int x = 0; x < width; x++) { int pixel = bi.getRGB(x, y); int red = colorModel.getRed(pixel); int green = colorModel.getGreen(pixel); int blue = colorModel.getBlue(pixel); int alpha = colorModel.getAlpha(pixel); boolean isWhite = (red == 255 && green == 255 && blue == 255 && alpha == 255); boolean isBlack = (red == 0 && green == 0 && blue == 0 && alpha == 255); sb.append( isWhite ? "_" : isBlack ? "X" : ("(" + red + "," + green + "," + blue + "," + alpha + ")")); bits <<= 1; if (!isWhite) { bits |= 1; } } sb.append(String.format(" (0x%03X)\n", bits)); } // Also include some of the font metrics. FontMetrics fm = g.getFontMetrics(); sb.append("fm: ascent=" + fm.getAscent() + " leading=" + fm.getLeading() + " charWidth('A')=" + fm.charWidth('A') + " descent=" + fm.getDescent() + " height=" + fm.getHeight() + "\n"); String actualGlyph = sb.toString(); g.dispose(); // The expected glyph and metrics. String expectedGlyph = "_________ (0x000)\n" + "____X____ (0x010)\n" + "___X_X___ (0x028)\n" + "___X_X___ (0x028)\n" + "__X___X__ (0x044)\n" + "__X___X__ (0x044)\n" + "__XXXXX__ (0x07C)\n" + "_X_____X_ (0x082)\n" + "_X_____X_ (0x082)\n" + "_X_____X_ (0x082)\n" + "_________ (0x000)\n" + "fm: ascent=10 leading=1 charWidth('A')=9 descent=3 height=14\n"; if (!expectedGlyph.equals(actualGlyph)) { // Currently, this is known to happen when using OpenJDK 6 // and 7, with 6 being close to right and 7 being very bad. // I also have reports of it happening on certain Mac OS/X // systems, but I haven't been able to determine what the // important factor there is. String warningMessage = "There is a problem with the font rendering. The glyph " + "for the letter 'A' should look like:\n" + expectedGlyph + "but it renders as:\n" + actualGlyph + "\n" + "This probably means there is a bug in the TrueType " + "font library. You might try a different Java version. " + "(I'm working on how to solve this permanently.)"; System.err.println(warningMessage); this.log(warningMessage); SwingUtil.errorMessageBox(null /*component*/, warningMessage); } }
From source file:com.projity.contrib.calendar.JXXMonthView.java
private void drawDay(boolean colored, boolean flagged, boolean today, Graphics g, String text, int x, int y) { Color defaultColor = g.getColor(); Font oldFont = getFont();/*from www. jav a2s . c o m*/ if (colored) { g.setColor(Color.LIGHT_GRAY); g.fillRect(_bounds.x, _bounds.y, _bounds.width, _bounds.height); g.setColor(defaultColor); } if (today) g.setColor(Color.BLUE); if (flagged) { g.setColor(Color.RED); g.setFont(_derivedFont); } g.drawString(text, x, y); g.setColor(defaultColor); g.setFont(oldFont); }
From source file:es.emergya.ui.gis.layers.MapViewerLayer.java
@Override public void paint(Graphics g, MapView mv) { parent = (CustomMapView) mv;/*from w w w .j a v a 2 s .com*/ int iMove = 0; zoom = mv.zoom(); LatLon cen = Main.proj.eastNorth2latlon(mv.getCenter()); center = new Point(OsmMercator.LonToX(cen.getX(), zoom), OsmMercator.LatToY(cen.getY(), zoom)); int tilex = center.x / Tile.SIZE; int tiley = center.y / Tile.SIZE; int off_x = (center.x % Tile.SIZE); int off_y = (center.y % Tile.SIZE); int w2 = mv.getWidth() / 2; int h2 = mv.getHeight() / 2; int posx = w2 - off_x; int posy = h2 - off_y; int diff_left = off_x; int diff_right = Tile.SIZE - off_x; int diff_top = off_y; int diff_bottom = Tile.SIZE - off_y; boolean start_left = diff_left < diff_right; boolean start_top = diff_top < diff_bottom; if (start_top) { if (start_left) { iMove = 2; } else { iMove = 3; } } else { if (start_left) { iMove = 1; } else { iMove = 0; } } // calculate the visibility borders int x_min = -Tile.SIZE; int y_min = -Tile.SIZE; int x_max = mv.getWidth(); int y_max = mv.getHeight(); // paint the tiles in a spiral, starting from center of the map boolean painted = true; int x = 0; while (painted) { painted = false; for (int i = 0; i < 4; i++) { if (i % 2 == 0) { x++; } for (int j = 0; j < x; j++) { if (x_min <= posx && posx <= x_max && y_min <= posy && posy <= y_max) { // tile is visible Tile tile = getTile(tilex, tiley, zoom); if (tile != null) { painted = true; tile.paint(g, posx, posy); if (tileGridVisible) { g.drawString(tile.getXtile() + ", " + tile.getYtile(), posx, posy + 12); g.drawRect(posx, posy, Tile.SIZE, Tile.SIZE); } } } Point p = move[iMove]; posx += p.x * Tile.SIZE; posy += p.y * Tile.SIZE; tilex += p.x; tiley += p.y; } iMove = (iMove + 1) % move.length; } } // outer border of the map int mapSize = Tile.SIZE << zoom; g.drawRect(w2 - center.x, h2 - center.y, mapSize, mapSize); if (LOG.isDebugEnabled()) { g.setColor(Color.LIGHT_GRAY); g.drawString("Tiles in cache: " + tileCache.getTileCount(), 50, 15); } // g.fillRect(0, 100, 300, 55); // g.setColor(Color.BLACK); // g.drawString("center: " + center.x + ", " + center.y, 5, 120); // g.drawString("zoom: " + zoom + " for scale:" + mv.getScale(), 5, // 150); }
From source file:edu.ku.brc.ui.ImageDisplay.java
@Override protected void paintComponent(Graphics g) { super.paintComponent(g); boolean doScale = true; int w = getWidth(); int h = getHeight(); Image dspImg = image;/*from www .j ava2 s . co m*/ boolean doDisplayImage = (image != null && (!isNoAttachment && status == kImageOK)) || isLoading; if (isLoading) { doDisplayImage = true; dspImg = IconManager.getImage("Loading").getImage(); } if (doDisplayImage && dspImg != null) { int imgW = dspImg.getWidth(null); int imgH = dspImg.getHeight(null); if (doScale && (imgW > w || imgH > h)) { double scaleW = 1.0; double scaleH = 1.0; double scale = 1.0; if (imgW > w) { scaleW = (double) w / imgW; } if (imgH > h) { scaleH = (double) h / imgH; } scale = Math.min(scaleW, scaleH); imgW = (int) (imgW * scale); imgH = (int) (imgH * scale); } int x = 0; int y = 0; if (imgW < w) { x = (w - imgW) / 2; } if (imgH < h) { y = (h - imgH) / 2; } g.drawImage(dspImg, x, y, imgW, imgH, null); } else if (doShowText) { GraphicsUtils.turnOnAntialiasedDrawing(g); String[] label = this.isNoAttachment ? (isFullImage ? noAttachmentStr : noThumnailStr) : loadingAttachmentStr; FontMetrics fm = g.getFontMetrics(); int spacing = 2; int yOffset = (h - (fm.getHeight() + spacing) * label.length) / 2; if (yOffset < 0) yOffset = 0; int y = yOffset + fm.getHeight(); for (String str : label) { g.drawString(str, (w - fm.stringWidth(str)) / 2, y); y += fm.getHeight() + 2; } } }