Update Jfreechart when update data from Webcam - jfreechart

My jfreeChart comes from frames of a webcam. I pass this frames and it generates a graphic of R, G and B colors of this frame. I want this chart do automatic update as I pass the frames. I've tried everything but nothing seens to work.
Any help is welcome.
class DaemonThread implements Runnable
{
protected volatile boolean runnable = false;
#Override
public void run()
{
synchronized(this)
{
while(runnable)
{
if(webSource.grab())
{
try
{
webSource.retrieve(frame);
Imgcodecs.imencode(".bmp", frame, mem);
Image im = ImageIO.read(new ByteArrayInputStream(mem.toArray()));
buff = (BufferedImage) im;
if(contHistograma==0) {
h = new Histo(buff);
contHistograma++;
}else{
h.update(buff);
}
webcamLabel.setIcon(new ImageIcon(buff));
Graphics g=webcamPanel.getGraphics();
if (g.drawImage(buff, 0, 0, getWidth(), getHeight() -150 , 0, 0, buff.getWidth(), buff.getHeight(), null))
if(runnable == false)
{
System.out.println("Going to wait()");
this.wait();
}
}
catch(Exception ex)
{
System.out.println("Error");
}
}
}
}
}
}
public class Histo{
private ChartFrame lineFrame;
private ArrayList<Integer> redArray;
private ArrayList<Integer> greenArray;
private ArrayList<Integer> blueArray;
public Histo(BufferedImage originalImage){
Color c;
redArray = new ArrayList<>();
greenArray = new ArrayList<>();
blueArray = new ArrayList<>();
for (int i = 0; i < originalImage.getWidth(null); i++) {
for (int j = 0; j < originalImage.getHeight(null); j++) {
c = new Color(originalImage.getRGB(i,j));
redArray.add(c.getRed());
greenArray.add(c.getGreen());
blueArray.add(c.getBlue());
}
}
Collections.sort(redArray);
Collections.sort(greenArray);
Collections.sort(blueArray);
XYSeriesCollection dataset = creatingDataset(redArray, greenArray, blueArray);
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart);
lineFrame = new ChartFrame("teste", chart);
lineFrame.add(chartPanel);
lineFrame.setVisible(true);
lineFrame.setSize(600, 450);
}
public void update(BufferedImage originalImage){
redArray.clear();
greenArray.clear();
blueArray.clear();
Color c;
for (int i = 0; i < originalImage.getWidth(null); i++) {
for (int j = 0; j < originalImage.getHeight(null); j++) {
c = new Color(originalImage.getRGB(i,j));
redArray.add(c.getRed());
greenArray.add(c.getGreen());
blueArray.add(c.getBlue());
}
}
Collections.sort(redArray);
Collections.sort(greenArray);
Collections.sort(blueArray);
XYSeriesCollection dataset = creatingDataset(redArray, greenArray, blueArray);
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart);
lineFrame.removeAll();
lineFrame.add(chartPanel);
lineFrame.revalidate();
lineFrame.setLayout(new BorderLayout());
lineFrame.repaint();
}
public static XYSeriesCollection creatingDataset(ArrayList<Integer> redArray,ArrayList<Integer> greenArray,ArrayList<Integer> blueArray){
int cont=1, cont2=1, cont3=1;
XYSeries series = new XYSeries("Red");
XYSeries series2 = new XYSeries("Green");
XYSeries series3 = new XYSeries("Blue");
for (int i = 0; i < redArray.size()-1; i++) {
if(redArray.get(i).intValue() == redArray.get(i+1).intValue()) {
cont++;
}else{
series.add(redArray.get(i).intValue(), cont);
cont=1;
}
}
for (int i = 0; i < greenArray.size()-1; i++) {
if(greenArray.get(i).intValue() == greenArray.get(i + 1).intValue()) {
cont2++;
}else{
series2.add(greenArray.get(i).intValue(), cont2);
cont2 = 1;
}
}
for (int i = 0; i < blueArray.size()-1; i++) {
if(blueArray.get(i).intValue() == blueArray.get(i+1).intValue()) {
cont3++;
}else{
series3.add(blueArray.get(i).intValue(), cont3);
cont3=1;
}
}
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
dataset.addSeries(series2);
dataset.addSeries(series3);
return dataset;
}
private JFreeChart createChart(final XYDataset dataset) {
JFreeChart result = ChartFactory.createXYLineChart("Gráfico XY", "Eixo X", "Eixo Y", dataset, PlotOrientation.VERTICAL, true, true, false);
final XYPlot plot = result.getXYPlot();
plot.setBackgroundPaint(new Color(0xffffe0));
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.lightGray);
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.lightGray);
final NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis(); //RANGE EIXO X
domainAxis.setRange(0, 260);
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); //RANGE EIXO Y
rangeAxis.setRange(0, 5000);
return result;
}
}

If someone else have this problem here is the answer:
Chartframe can't get rid of chartpanel, so I made Chartpanel a atribute.
After that I update my dataset and did this:
JFreeChart chart = createChart(dataset);
chartPanel.setChart(chart);
lineFrame.setLayout(new BorderLayout());
lineFrame.repaint();
Problem solved.

Related

Why does this image rendering benchmark crash on IOS but not in the simulator?

I tried to get a grasp of image rendering performance and created some code which draws full screen images using mutable images and PNGs.
The code runs fine in the simulator but on an iPhone SE it crashes after 50 seconds or short before a million images.
Is it a bug or is there another explanation since it doesn't crash in the simulator and I cannot see a memory leak in jvisualvm?
Here is the code:
public class FormMeasureImage extends Form implements Painter {
abstract class Wallpaper implements Painter {
private Component componentParent;
public Wallpaper(Component aComponentParent) {
componentParent = aComponentParent;
}
public void paint(Graphics aGraphics, Rectangle aRectangle) {
aGraphics.drawImage(
getImage(new Dimension(componentParent.getWidth(), componentParent.getHeight())),
0,
0);
}
public abstract Image getImage(Dimension aDimension);
}
class WallpaperTiledIcons extends Wallpaper {
private Image image;
private Dimension dimension;
public WallpaperTiledIcons(Component aComponentParent) {
super(aComponentParent);
}
public Image getImage(Dimension aDimension) {
if ((null == image || !dimension.equals(aDimension)) && null != aDimension) {
dimension = new Dimension(aDimension);
Label labelPattern = new Label("1234567890");
Style styleLabelPattern = labelPattern.getAllStyles();
styleLabelPattern.setBorder(Border.createEmpty());
styleLabelPattern.setMargin(0, 0, 0, 0);
// byte[] bytes = new byte[4];
// Arrays.fill(bytes, Style.UNIT_TYPE_PIXELS);
// styleLabelPattern.setPaddingUnit(bytes);
styleLabelPattern.setPadding(0, 0, 0, 1);
Dimension preferredSizeLabelPattern = labelPattern.getPreferredSize();
labelPattern.setSize(preferredSizeLabelPattern);
Image imagePattern = Image.createImage(
preferredSizeLabelPattern.getWidth(),
preferredSizeLabelPattern.getHeight(),
0x00000000);
Graphics graphicsImagePattern = imagePattern.getGraphics();
graphicsImagePattern.setAlpha(255);
labelPattern.paint(graphicsImagePattern);
image = Image.createImage(
aDimension.getWidth(),
aDimension.getHeight(),
0xff606060);
Graphics graphics = image.getGraphics();
if (graphics.isAntiAliasingSupported()) {
graphics.setAntiAliased(true);
}
int canvasWidth = preferredSizeLabelPattern.getWidth(), canvasHeight = preferredSizeLabelPattern.getHeight();
int[] clip = graphics.getClip();
Rectangle rectangleClip = new Rectangle(clip[0], clip[1], clip[2], clip[3]);
int columns = (rectangleClip.getX() + rectangleClip.getWidth()) / canvasWidth + 1;
int rows = (rectangleClip.getY() + rectangleClip.getHeight()) / canvasHeight + 1;
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
int x = canvasWidth * column;
int y = canvasHeight * row;
Rectangle rectangle = new Rectangle(x, y, canvasWidth, canvasHeight);
if (!rectangleClip.intersects(rectangle)) {
continue;
}
graphics.drawImage(imagePattern, x, y);
}
}
}
return image;
}
}
abstract class Stage {
long millisTotal;
long tally;
TextArea textArea;
public Stage(String aName) {
textArea = new TextArea();
textArea.setEditable(false);
getContentPane().add(textArea);
stages.add(this);
}
abstract void perform();
abstract boolean isPainted();
}
private Wallpaper wallpaper;
private List<Stage> stages = new ArrayList<>();
private Iterator<Stage> iteratorStages;
private Image imageEncoded;
public FormMeasureImage() {
super("FormMeasureImage", new BoxLayout(BoxLayout.Y_AXIS));
setScrollableX(false);
setScrollableY(true);
Style styleForm = getAllStyles();
styleForm.setBgTransparency(255);
styleForm.setBgPainter(this);
TextArea textArea = new TextArea();
textArea.setEditable(false);
textArea.setText("Measuring image throughput.");
add(textArea);
}
#Override
public void paint(Graphics aGraphics, Rectangle aRectangle) {
if (null == iteratorStages) {
new Stage("create") {
void perform() {
long millisBefore = System.currentTimeMillis();
wallpaper = new WallpaperTiledIcons(FormMeasureImage.this);
wallpaper.getImage(aRectangle.getSize());
millisTotal += System.currentTimeMillis() - millisBefore;
tally++;
textArea.setText("create: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return false;
}
};
new Stage("mutable") {
void perform() {
long millisBefore = System.currentTimeMillis();
for (int index = 0; index < 1000; index++) {
wallpaper.paint(aGraphics, aRectangle);
tally++;
}
millisTotal += System.currentTimeMillis() - millisBefore;
textArea.setText("mutable: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return true;
}
};
new Stage("encoding") {
void perform() {
long millisBefore = System.currentTimeMillis();
try {
millisBefore = System.currentTimeMillis();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.getImageIO().save(wallpaper.getImage(null), byteArrayOutputStream, ImageIO.FORMAT_PNG, 1);
byteArrayOutputStream.close();
imageEncoded = Image.createImage(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
tally++;
millisTotal += System.currentTimeMillis() - millisBefore;
textArea.setText("encoding: " + millisTotal + " / " + tally);
} catch (IOException e) {
throw new RuntimeException(e.toString());
}
millisTotal += System.currentTimeMillis() - millisBefore;
tally++;
textArea.setText("encoding: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return false;
}
};
new Stage("encoded") {
void perform() {
long millisBefore = System.currentTimeMillis();
for (int index = 0; index < 1000; index++) {
aGraphics.drawImage(
imageEncoded,
0,
0);
tally++;
}
millisTotal += System.currentTimeMillis() - millisBefore;
textArea.setText("encoded: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return true;
}
};
iteratorStages = stages.iterator();
}
while (!perform().isPainted()) {;}
}
private Stage perform() {
if (!iteratorStages.hasNext()) {
iteratorStages = stages.iterator();
}
Stage stage = iteratorStages.next();
stage.perform();
return stage;
}
}
It seems that the test case included an EDT violation of decoding off the EDT. This can work for some cases but because of the heavy usage it crashes.
Making UI code threadsafe is a difficult task which is doubly so cross platforms.

Image Viewer auto slide codenamone

How can i auto slide the imageViewer for instance in the interval of 3 seconds.
Or is there any other component that can do the auto swipe task.
ImageViewer imv = new ImageViewer();
DefaultListModel<Image> images = new DefaultListModel<Image>(new Image[]{a, thumbnail1, thumbnail2});
imv.setImage(images.getItemAt(0));
imv.setImageList(images);
imv.setSwipePlaceholder(Image.createImage(100, 100));
Declare this global static variable:
private static int slideIndex = 0;
//And this UITimer
UITimer t;
And then try out below code
final ImageViewer imv = new ImageViewer();
final DefaultListModel<Image> images = new DefaultListModel<Image>(new Image[]{a, thumbnail1, thumbnail2});
imv.setImage(images.getItemAt(0));
imv.setImageList(images);
imv.setSwipePlaceholder(Image.createImage(100, 100));
Runnable r = new Runnable() {
public void run() {
if (slideIndex < images.getSize()) {
slideIndex++;
} else {
slideIndex = 0;
}
Image nextImage = (Image) images.getItemAt(slideIndex);
if (nextImage != null) {
imv.setImage(nextImage);
}
}
};
if (t == null) {
t = new UITimer(r);
}
if (t != null) {
t.schedule(3000, true, f); //3 seconds
}

How to let Stage show the pictures after timer

After I click start button, my program will not show the second scene and thread , until the thread is finish. And the thread will not run correctly(grass didn't increase).
public class test111 extends Application {
private static int grass_i=130;
private static int grass_j=200;
private static int[][] map = new int[grass_i][grass_j];//草地資料grassdata
private static int totalgrass; //grass total number
private static int totalgrassrest; //grass rest number
private static int months=1; //月
private Timer timer;//時間
//GUI
Scene menusc ;
//START後的視窗
BorderPane bpAll = new BorderPane();
Pane playView = new Pane();
Scene mainsc = new Scene(bpAll);
//草
Image littlegrassImg = new Image(getClass().getResourceAsStream("map_littlegrass.png"));
Image midiumgrassImg = new Image(getClass().getResourceAsStream("map_midiumgrass.png"));
Image muchgrassImg = new Image(getClass().getResourceAsStream("map_muchgrass.png"));
Rectangle2D[][] viewportRect = new Rectangle2D[130][200];
private static ImageView[][] mapView = new ImageView[130][200];
//時間
#Override
public void start(Stage primaryStage) throws InterruptedException {
//MENU
Pane menu = new Pane();
menusc = new Scene(menu);
menu.setPrefSize(1000, 800);
Image MenuImg = new Image(getClass().getResourceAsStream("Menu_title.jpg"));
Image StartImg = new Image(getClass().getResourceAsStream("Start.jpg"));
menu.getChildren().add(new ImageView(MenuImg));
Button StartBt = new Button();
StartBt.setPrefSize(450, 150);
StartBt.setGraphic(new ImageView(StartImg));
StartBt.setMaxSize(450, 150);
StartBt.setLayoutX(300);
StartBt.setLayoutY(600);
menu.getChildren().addAll(new ImageView(MenuImg),StartBt);
primaryStage.setMinHeight(800);//固定視窗大小fix the size of Stage
primaryStage.setMinWidth(1000);//固定視窗大小fix the size of Stage
primaryStage.setMaxHeight(800);//固定視窗大小fix the size of Stage
primaryStage.setMaxWidth(1000);//固定視窗大小fix the size of Stage
primaryStage.setScene(menusc);
primaryStage.setTitle("Hypnos' yard");
//START
StartBt.setOnAction(e->{
BorderPane bp2 = bp2();
menusc = new Scene(bp2);
primaryStage.setScene(menusc);
});
primaryStage.show();
}
public BorderPane bp2(){
playView = playView();
bpAll = new BorderPane();
bpAll.setPrefSize(1000, 800);
playView.setPrefSize(1000, 650); //庭院
bpAll.setTop(playView);
Random ran = new Random();
totalgrass = (ran.nextInt(50)*1000)+48000;
totalgrassrest = totalgrass;
grasscreate();
//設定初始草地construct the initial grass
grassGraphicsLoading(); //loading grass pictures
return bpAll;
}
public Pane playView(){
playView = new Pane();
while(months<12){
timer = new Timer();
TimerTask task = new TimerTask(){
public void run(){
month();
}
};//after program executing 0.2s, a month past
timer.schedule(task, 200);
try {
Thread.sleep(200);
}
catch(InterruptedException e6) {
}
timer.cancel();
}
return playView;
}
//月month
protected void month(){
if(months<13){
grassgrow(totalgrass*2);//grass growth
Platform.runLater(new Runnable(){
#Override
public void run(){
grassGraphicsLoading();
}
});
months++;
}
}
//把草地資料帶入圖形loading grass pictures
private void grassGraphicsLoading(){
for (int i = 0; i < grass_i; i++) { // 設定imageView的圖形和位置
for (int j = 0; j < grass_j; j++) {
viewportRect[i][j] = new Rectangle2D(j * 5, i * 5, 5, 5);
if (170 <= j && j <= grass_j - 1) {
mapView[i][j] = new ImageView(muchgrassImg);
} else if (140 <= j && j < 170) {
mapView[i][j] = new ImageView(muchgrassImg);
} else {
if (map[i][j] == 0) {
mapView[i][j] = new ImageView(littlegrassImg);
} else if (map[i][j] == 1 || map[i][j] == 2) {
mapView[i][j] = new ImageView(midiumgrassImg);
} else {
mapView[i][j] = new ImageView(muchgrassImg);
}
}
playView.getChildren().add(mapView[i][j]);
mapView[i][j].setViewport(viewportRect[i][j]);
mapView[i][j].setX(j * 5);
mapView[i][j].setY(i * 5);
}
}
}
public static void main(String[] args) {
launch(args);
}
// 每經過30天(一個月)草地+1grassgrowth
protected void grassgrow(int sum) {
for (int i = 0; i < grass_i; i++) {
for (int j = grass_j - 1; j >= 0; j--) {
if (map[i][j] < 4 && totalgrass <sum) {
map[i][j] += 1;
totalgrass++;
}
if (totalgrass == 104000||totalgrass ==sum) {
break;
}
}
}
}
//建構草地construct grass
protected void grasscreate() {
for (int j = grass_j - 1; j >= 0; j--) {
for (int i = grass_i - 1; i >= 0; i--) {
if (170 <= j && j <= grass_j - 1) {
map[i][j] = 0;
} else if (140 <= j && j < 170) {
map[i][j] = 4;
totalgrassrest -= 4;
} else if (totalgrassrest <= 0) {
map[i][j] = 0;
} else if (4 * (j + 1) * grass_i <= totalgrassrest) {
map[i][j] = 4;
totalgrassrest -= 4;
} else if (totalgrassrest < 4) {
map[i][j] = totalgrassrest;
totalgrassrest = 0;
} else {
map[i][j] = rancreate();
totalgrassrest -= map[i][j];
}
}
}
totalgrass -= totalgrassrest;
totalgrassrest = 0;
}
// 一格(5X5)內草地數量隨機1-4平米z there is 1-4 grass inside a rectangle
private int rancreate() {
Random ran = new Random();
int grass = ran.nextInt(5);
return grass;
}
}`

JFreeChart XY plot: change domain scale

I create the following XY chart:
In this instance, I have two axes, each with two series. And each series has 39 points.
I would like to know how to change the scale of the domain axis, so for example instead of 0-39, it would show 0-3.9.
How can this be achieved? My code for the graph is below:
private final static int SERIES_MIN = 0;
private final static int SERIES_MAX = 1;
private JFreeChart createXYLineChart(String title) {
XYDataset voltageDataset = createXYVoltageDataset();
XYDataset currentDataset = createXYCurrentDataset();
XYLineAndShapeRenderer rVoltage = new XYLineAndShapeRenderer();
rVoltage.setSeriesPaint(SERIES_MIN, new Color(0xAA, 0xAA, 0xFF));
rVoltage.setSeriesPaint(SERIES_MAX, new Color(0x00, 0x00, 0xAA));
rVoltage.setSeriesShapesVisible(SERIES_MIN, false);
rVoltage.setSeriesShapesVisible(SERIES_MAX, false);
float dashVoltage[] = {1.0f, 5f}; // on, off
rVoltage.setSeriesStroke(SERIES_MIN, new BasicStroke(2.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 5, dashVoltage, 0));
rVoltage.setSeriesStroke(SERIES_MAX, new BasicStroke(1f));
XYLineAndShapeRenderer rCurrent = new XYLineAndShapeRenderer();
rCurrent.setSeriesPaint(SERIES_MIN, new Color(0x66, 0xAA, 0x66));
rCurrent.setSeriesPaint(SERIES_MAX, new Color(0x00, 0x44, 0x00));
rCurrent.setSeriesShapesVisible(SERIES_MIN, false);
rCurrent.setSeriesShapesVisible(SERIES_MAX, false);
float dashCurrent[] = {1.0f, 5f}; // on, off
rCurrent.setSeriesStroke(SERIES_MIN, new BasicStroke(2.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 5, dashCurrent, 0));
rCurrent.setSeriesStroke(SERIES_MAX, new BasicStroke(1));
JFreeChart chart = ChartFactory.createXYLineChart("Profile", "Set Current", "Voltage", null);
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDataset(SERIES_MIN, voltageDataset);
plot.setRenderer(SERIES_MIN, rVoltage);
plot.setDataset(SERIES_MAX, currentDataset);
plot.setRenderer(SERIES_MAX, rCurrent);
plot.setRangeAxis(SERIES_MAX, new NumberAxis("Actual Current"));
plot.mapDatasetToRangeAxis(SERIES_MAX, SERIES_MAX); //2nd dataset to 2nd y-axi
plot.setBackgroundPaint(new Color(0xFF, 0xFF, 0xFF));
plot.setDomainGridlinePaint(new Color(0x00, 0x00, 0xff));
plot.setRangeGridlinePaint(new Color(0xff, 0x00, 0x00));
return chart;
}
private XYDataset createXYVoltageDataset() {
final XYSeries s1 = new XYSeries("Min Voltage");
final XYSeries s2 = new XYSeries("Max Voltage");
for (int i = 0; i < profile.getNumSteps(); i++) s1.add(i, profile.getStepMinVoltage(i));
for (int i = 0; i < profile.getNumSteps(); i++) s2.add(i, profile.getStepMaxVoltage(i));
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(s1);
dataset.addSeries(s2);
return dataset;
}
private XYDataset createXYCurrentDataset() {
final XYSeries s1 = new XYSeries("Min Current");
final XYSeries s2 = new XYSeries("Max Current");
for (int i = 0; i < profile.getNumSteps(); i++){
s1.add(i, profile.getStepMinCurrent(i));
}
for (int i = 0; i < profile.getNumSteps(); i++) s2.add(i, profile.getStepMaxCurrent(i));
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(s1);
dataset.addSeries(s2);
return dataset;
}
You should be able to use setRange() on the domain axis.
NumberAxis domainAxis = new NumberAxis("Set Current");
domainAxis.setRange(0, 3.9);
plot.setDomainAxis(SERIES_MAX, domainAxis);

WPF: Create XpsDocument Pagination

I am trying to create a Paginator that will in turn create an XpsDocument that I can preview with the and then print. I have the following code that I found on the web but do not understand how it is working.
The issue I am having is that if I run this as is, the pages are generated successfully. If I comment out the lines within OnRender() that generate the actual values of data (all the lines after Random...) I get pages that are about one row high and no text on them but they appear to be the correct length. What is it that is keeping the values of "Row Number" & "Column i" from being shown?
I have included 2 screen shots to illustrate.
public class TaxCodePrintPaginator : DocumentPaginator
{
private int _RowsPerPage;
private Size _PageSize;
private int _Rows;
private List<TaxCode> _dataList;
public TaxCodePrintPaginator(List<TaxCode> dt, int rows, Size pageSize)
{
_dataList = dt;
_Rows = rows;
PageSize = pageSize;
}
public override DocumentPage GetPage(int pageNumber)
{
int currentRow = _RowsPerPage * pageNumber;
var page = new PageElement(currentRow, Math.Min(_RowsPerPage, _Rows - currentRow))
{
Width = PageSize.Width,
Height = PageSize.Height
};
page.Arrange(new Rect(new Point(0, 0), PageSize));
return new DocumentPage(page);
}
public override bool IsPageCountValid
{ get { return true; } }
public override int PageCount
{ get { return (int)Math.Ceiling(_Rows / (double)_RowsPerPage); } }
public override Size PageSize
{
get { return _PageSize; }
set
{
_PageSize = value;
_RowsPerPage = 40;
//Can't print anything if you can't fit a row on a page
Debug.Assert(_RowsPerPage > 0);
}
}
public override IDocumentPaginatorSource Source
{ get { return null; } }
}
public class PageElement : UserControl
{
private const int PageMargin = 75;
private const int HeaderHeight = 25;
private const int LineHeight = 20;
private const int ColumnWidth = 140;
private int _CurrentRow;
private int _Rows;
public PageElement(int currentRow, int rows)
{
Margin = new Thickness(PageMargin);
_CurrentRow = currentRow;
_Rows = rows;
}
private static FormattedText MakeText(string text)
{
return new FormattedText(text, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Tahoma"), 14, Brushes.Black);
}
public static int RowsPerPage(double height)
{
return (int)Math.Floor((height - (2 * PageMargin)
- HeaderHeight) / LineHeight);
}
protected override void OnRender(DrawingContext dc)
{
Point curPoint = new Point(0, 0);
dc.DrawText(MakeText("Row Number"), curPoint);
curPoint.X += ColumnWidth;
for (int i = 1; i < 4; i++)
{
dc.DrawText(MakeText("Column " + i), curPoint);
curPoint.X += ColumnWidth;
}
curPoint.X = 0;
curPoint.Y += LineHeight;
dc.DrawRectangle(Brushes.Black, null, new Rect(curPoint, new Size(Width, 2)));
curPoint.Y += HeaderHeight - LineHeight;
Random numberGen = new Random();
for (int i = _CurrentRow; i < _CurrentRow + _Rows; i++)
{
dc.DrawText(MakeText(i.ToString()), curPoint);
curPoint.X += ColumnWidth;
for (int j = 1; j < 4; j++)
{
dc.DrawText(MakeText(numberGen.Next().ToString()), curPoint);
curPoint.X += ColumnWidth;
}
curPoint.Y += LineHeight;
curPoint.X = 0;
}
}
}
Before
After

Resources