开发者

How to rendering fraction in Swing JComponents

Basically Swing JComponents are able to display numbers in fractions in this form 2 2/3. How can I paint fraction in the nicest form, for example 2⅔?

.

EDIT

.

as 开发者_如何学Csee I have only one way JTable inside JSpinner with one TableColumn and TableRow (that could simulated plain JtextField too), where TableRenderer could be some of JTextComponent formatted by using Html and on TableCellEdit event the TableEditor to swith to the plain JFormattedTextField,

is there another way, could it be possible with plain J(Formatted)TextField too ???


On reflection, Unicode fractions among the Latin-1 Supplement and Number Forms offer limited coverage, and fancy equations may be overkill. This example uses HTML in Swing Components.

Addendum: The approach shown lends itself fairly well to rendering mixed numbers. For editing, key bindings to + and / could be added for calculator-style input in a text component. I've used org.jscience.mathematics.number.Rational to model rational numbers, and this parser could be adapted to evaluating rational expressions.

How to rendering fraction in Swing JComponents

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/** @see https://stackoverflow.com/questions/7448216 */
public class HTMLFractions extends JPanel {

    private static int N = 8;

    public HTMLFractions() {
        this.setLayout(new GridLayout(N, N, N, N));
        this.setBorder(BorderFactory.createEmptyBorder(N, N, N, N));
        for (int r = 0; r < N; r++) {
            for (int c = 0; c < N; c++) {
                this.add(create(r + N, r + 1, c + 2));
            }
        }
    }

    private JLabel create(int w, int n, int d) {
        StringBuilder sb = new StringBuilder();
        sb.append("<html><body>");
        sb.append(w);
        sb.append("<sup>");
        sb.append(n);
        sb.append("</sup>");
        sb.append("<font size=+1>/<font size=-1>");
        sb.append("<sub>");
        sb.append(d);
        sb.append("</sub>");
        sb.append("</html></body>");
        JLabel label = new JLabel(sb.toString(), JLabel.CENTER);
        label.setBorder(BorderFactory.createLineBorder(Color.lightGray));
        return label;
    }

    private void display() {
        JFrame f = new JFrame("HTMLFractions");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new HTMLFractions().display();
            }
        });
    }
}


Use the Java2D API. The is an excellent book on it from O'Reilly.

1- Use the font you like. 2- Convert the Glyphs you need (e.g. "2" "/" and "3") into Java2D shapes. 3- Use the Java@d method to scales and place the shapes together

4- This part depends on the component. I think a lot of components take some kind of image instead of text. Convert your shapes into whatever fits into the components you w ant.

5- This should look really professional if you do a good job :)

Come on give me 50!!!

=============

Thanks so much for the points. Here is an example of how to do the first step. It'll show how to get an instance of enter code here Shape from a character in the font of your choice.

Once you have your Shape You can use Graphics2D to create the image you want (scale, compose, etc). All the swing components are different but all have a graphics context. Using the graphics content you can draw on any Swing Component. You can also make transparent layers and stick a transport JPanel over anything you want. If you just want to display a fraction on a label that's easy. If you had some sort of word processor in mind that's hard.

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

public class Utils {

  public static Shape generateShapeFromText(Font font, char ch) {
    return generateShapeFromText(font, String.valueOf(ch));
  }

  public static Shape generateShapeFromText(Font font, String string) {
    BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = img.createGraphics();

    try {
      GlyphVector vect = font.createGlyphVector(g2.getFontRenderContext(), string);
      Shape shape = vect.getOutline(0f, (float) -vect.getVisualBounds().getY());

      return shape;
    } finally {
      g2.dispose();
    }
  }
}


You can use the approach based on this http://java-sl.com/fraction_view.html

The only difference is positioning subviews for numerator and denominator.


Unicode has a set of characters that will let you produce fractions without having to do special formatting, e.g., ⁴⁄₉ or ⁵⁶⁄₁₀₀.

You could set up an array of superscript digits, and an array of subscript digits, and convert your numbers to strings of these digits, and then combine them with the fraction slash in between.

Advantages are that it's more general (you can use the code in other contexts), and the result will tend to look better than if you tried to reproduce it using HTML formatting. Of course, you need to have Unicode fonts on your system, but most systems do these days.

A possible implementation in code:

    public String diagonalFraction(int numerator, int denominator) {
    char numeratorDigits[] = new char[]{
            '\u2070','\u00B9','\u00B2','\u00B3','\u2074',
            '\u2075','\u2076','\u2077','\u2078','\u2079'};
    char denominatorDigits[] = new char[]{
            '\u2080','\u2081','\u2082','\u2083','\u2084',
            '\u2085','\u2086','\u2087','\u2088','\u2089'};
    char fractionSlash = '\u2044';

    String numeratorStr = new String();
    while(numerator > 0){
        numeratorStr = numeratorDigits[numerator % 10] + numeratorStr;
        numerator = numerator / 10;
    }
    String denominatorStr = new String();
    while(denominator > 0){
        denominatorStr = denominatorDigits[denominator % 10] + denominatorStr;
        denominator = denominator / 10;
    }   
    return numeratorStr + fractionSlash + denominatorStr;
}


You would have to find a font that prints fractions in what you're calling nicest form, then write a method to convert the character string of your fraction into the character code of the corresponding nicest form fraction.


Special fonts method:

The special fonts method might be a really good solution too.

You are going to need a good font editor.

Create ten numbers just for the top number of the fraction, a special slash or line symbol for the middle, and ten numbers just for bottom digits.

The only problem is that it's got to look good and that requires that the spacing of the top/slash/and button all close to together, actually overlapping horizontally. The good news is fonts support this, and a good font editor will. The swing text components probably don't. You need to write your own text component of find a component that already lets you fine position the fonts. This is the different between test editing/ word processing and text typography.

But I also have another idea :)

You could do fractions with a horizontal bar instead of a diagonal slash.

123
---
456

This way font need not overlap and can be laid out by the editor in the standard way. The trick is to have the above be three characters next to each other.

1 2 3
- - -
4 5 6

So that's one hundred different characters you need for all combinations.

The only problem with this (in addition to having to create 100 characters) is if you have and odd number of digits in the top and even in the bottom or vise verse it will look like this:

 12
---
456
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜