I am trying to make a custom widget: for displaying a processor register which has a name, a value and can be displayed in octal/decimal hexa. The code is shown at the bottom. I receive better result when I use the code as shown (i.e I insert QRadioButtons):
If I use
mainLayout->addWidget(DisplayMode);
instead (I guess this is the correct method) then the resulting picture is
Do I misunderstand something? What is wrong?
RegisterWidget::RegisterWidget(QWidget *parent)
:QFrame (parent)
{
mValue = 0;
mName = "";
setFrameStyle(QFrame::Panel | QFrame::Sunken);
QHBoxLayout *mainLayout = new QHBoxLayout(this);
label = new QLabel(tr("mName"),this);
label->setText(mName);
label->setLineWidth(2);
QGroupBox *DisplayMode = new QGroupBox("");
QRadioButton *OctalR = new QRadioButton(this);
QRadioButton *DecimalR = new QRadioButton(this);
DecimalR->setChecked(true); DecimalR->setDown(true);
QRadioButton *HexaR = new QRadioButton(this);
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(OctalR);
hbox->addWidget(DecimalR);
hbox->addWidget(HexaR);
hbox->addStretch(1);
DisplayMode->setLayout(hbox);
mainLayout->addWidget(label);
Value = new QLCDNumber(this);
Value->setDigitCount(8);
Value->setSegmentStyle(QLCDNumber::Flat);
Value->display(mValue);
mainLayout->addWidget(Value);
/* mainLayout->addWidget(DisplayMode);*/
mainLayout->addWidget(OctalR);
mainLayout->addWidget(DecimalR);
mainLayout->addWidget(HexaR);
setLineWidth(3);
setLayout(mainLayout);
connect(OctalR, SIGNAL(clicked()), this, SLOT(setOctal()));
connect(DecimalR, SIGNAL(clicked()), this, SLOT(setDecimal()));
connect(HexaR, SIGNAL(clicked()), this, SLOT(setHexa()));
}
Call QLayout::setContentsMargins() for both mainLayout and hbox. Try (3, 3, 3, 3) as parameters for a starting point and tweak. Layouts have default margins of 11 pixels on most platforms, according to the docs.
Related
I'm struggling with Cannonjs physics lib, I got a sphere body with a changing quaternion, I just want that body to move forward according to its quaternion. I found many topics related to that but none of the suggested codes is working.
Is it a simple way to achieve that simple task?
So far I tried the solution given here but the using of vmult() method do not change the vector3 at all...
body.quaternion = new CANNON.Quaternion(0,1,0,0); // Whatever value you put here will not change the result of the vmult() operation below
var localVelocity = new CANNON.Vec3(0, 0, 1);
var worldVelocity = body.quaternion.vmult(localVelocity); //-> worldVelocity = (0,0,1)
body.velocity.copy(worldVelocity);
Try to set and not copy the body.velocity, this way:
let directionVector = new CANNON.Vec3(0, 0, 1);
directionVector.z -= moveDistance;
directionVector = vehicleBody.quaternion.vmult( directionVector );
vehicleBody.velocity.set( directionVector.x, directionVector.y, directionVector.z );
EDIT : OK, It was my css page which had a rule on path, 'cause I use svg a lot. Removed that rule and the problem was gone !
I'm facing something pretty annoying and which I do not understand.
I'm using amChart to make a XY chart with multiple series. Not that hard.
The thing is, I can't customize my series ! Bullets and legend are ok, but not series.
Here's a screenshot for better understanding :
MyWeirdChart (new OP can't embed images, sorry)
As you can see I have my custom bullet pushed on my series and my legend is exactly what I want for my chart BUT series are staying unchanged.
Here is my JS draw function :
function drawChart(dateArray, casesArray, deathsArray, healedArray, hospitalizationsArray, reanimationsArray) {
am4core.useTheme(am4themes_animated);
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.data = generateChartData(dateArray, casesArray, deathsArray, healedArray, hospitalizationsArray, reanimationsArray);
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
function pushSeries(field, name, color) {
let series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = field;
series.dataFields.dateX = "date";
series.name = name;
series.tooltipText = name + ": [b]{valueY}[/]";
series.stroke = am4core.color(color);
series.strokeWidth = 3;
series.fill = am4core.color(color);
series.fillOpacity = 0.5;
let bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color(color);
bullet.circle.strokeWidth = 2;
bullet.circle.fill = am4core.color(color);
bullet.circle.fillOpacity = 0.5;
bullet.circle.radius = 3;
}
pushSeries("cases", "Cas confirmés", "#32B3E3");
pushSeries("healed", "Guéris", "#00C750");
pushSeries("hospitalizations", "Hospitalisations", "#FFBB33");
pushSeries("reanimations", "Réanimations", "#FE3446");
pushSeries("deaths", "Morts", "black");
chart.cursor = new am4charts.XYCursor();
chart.scrollbarX = new am4core.Scrollbar();
chart.legend = new am4charts.Legend();
chart.cursor.maxTooltipDistance = 0;
}
Did I miss something ? I crawled forums and documentations and I'm now helpless.
My code is in my webpack app.js file. But I include amCharts with HTML scripts,
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
not with webpack import. But I guess that if this was the problem, I would not be able to draw a chart at all.
OK, It was my css page which had a rule on path, 'cause I use svg a lot. Removed that rule and the problem was gone !
Is there a Java or Nodejs library that can move existing text in a PDF file?
I'd like to extract all the text nodes, then move some of them to a new location based on some conditions.
I tried PdfClown, galkahana/HummusJS, Hopding/pdf-lib, but seems they don't have exactly what I need.
can anyone help? thanks
After inspecting the variables, I figured out how to move text, here is the code
PrimitiveComposer composer = new PrimitiveComposer(page);
ContentScanner scanner = composer.getScanner();
tranverse(scanner);
composer.flush();
...
while (level.moveNext()){
ContentObject content = level.getCurrent();
if (content instanceof Text){
...
List<ContentObject> objects = text.getBaseDataObject().getObjects();
for(ContentObject co: objects){
if(co instanceof SetTextMatrix){
List<PdfDirectObject> operands = ((SetTextMatrix)co).getOperands();
PdfInteger y = (PdfInteger)operands.get(5);
operands.set(5, new PdfInteger(y.getIntValue()-100));
}
}
I'm trying to create a simple pdf multi-page document with fields in it. To do that I have a template pdf which in the code I clone this template as many times as needed in order to create the document itself.
The problem comes with inserting some data in it. The type of data I try to insert to the document is not supposed to change across the pages. Rather than that, it stays static in all pages, Like the "Pages" digit that represents the number of the pages that this document contains.
Now, Inside my template pdf I have some text fields like, for instance, "Shipper1" and "Pages". I want to be able to insert my data into this text fields so that all the pages in the document will have this values in their "Shipper1" and "Pages" fields.
My code currently does that only on the first page. It shows the data perfectly. On the other hand, when I go to another page, the data isn't shown there. It's just displays an empty field.
Here is the code where I initiate the pdf document:
static void initiatePdf() {
// Initiate a new PDF Box object and get the acro form from it
File file = new File(Constants.Paths.EMPTY_DOC)
PDDocument tempDoc
Evaluator evaluator = new Evaluator(metaHolder)
int numPages = evaluator.getNumOfPagesRequired(objects)
FieldRenamer renamer = new FieldRenamer()
PDResources res = new PDResources()
COSDictionary acroFormDict = new COSDictionary()
List<PDField> fields = []
Closure isFieldExist = {List<PDField> elements, String fieldName ->
elements.findAll{it.getFullyQualifiedName() == fieldName}.size() > 0
}
for(int i = 0; i < numPages; i++) {
tempDoc = new PDDocument().load(file)
PDDocumentCatalog docCatalog = tempDoc.getDocumentCatalog()
PDAcroForm acroForm = docCatalog.acroForm
PDPage page = (PDPage) docCatalog.getPages().get(0)
renamer.setCurrentForm(acroForm)
if(i == 0) {
res = acroForm.getDefaultResources()
acroFormDict.mergeInto(acroForm.getCOSObject())
renamer.renameFields(1)
} else
renamer.renameFields(i*10+1)
List<PDField> newFields = acroForm.fields.findAll { PDField newField ->
isFieldExist(fields, newField.getFullyQualifiedName()) == false
}
fields.addAll(newFields)
document.addPage(page)
}
PDAcroForm acroForm = new PDAcroForm(document, acroFormDict);
acroForm.setFields(fields)
acroForm.setDefaultResources(res);
document.documentCatalog.setAcroForm(acroForm)
}
A couple of things first:
metaHolder instance holds the information about all
the fields that reside inside the acro form. the info is: Field Name, Field Widget Width, Field Font and Font size
evaluator is just and instance of the Evaluator class. Its purpose is to analyze the dynamic data and decide how many pages will take to contain all that text data.
Here is where I try to populate the fields with text:
static void populateData() {
def properties = ["$Constants.Fields.SHIPPER" : "David"]
FieldPopulater populater = new FieldPopulater(document, metaHolder)
populater.populateStaticFields(properties)
}
FieldPopulater class:
package app.components
import app.StringUtils
import app.components.entities.DGObject
import app.components.entities.FieldMeta
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm
import org.apache.pdfbox.pdmodel.interactive.form.PDField
/**
* Created by David on 18/10/2016.
*/
class FieldPopulater {
PDAcroForm acroForm
FormMetaHolder metaHolder
FieldPopulater(PDDocument document, FormMetaHolder metaHolder) {
this.acroForm = document.getDocumentCatalog().acroForm
this.metaHolder = metaHolder
}
void populateStaticFields(properties) {
List<PDField> fields = []
properties.each {fieldName, data ->
FieldMeta fieldMeta = metaHolder.getMetaData(fieldName)
fields = acroForm.fields.findAll { PDField field ->
String currentName = field.getFullyQualifiedName()
char lastChar = currentName[-1]
if(Character.isDigit(lastChar)) {
currentName = currentName.substring(0,currentName.size()-1)
}
currentName == fieldName
}
if(fields.size() > 1) {
int counter = 1
String tempData = data
String currentFitData
while(tempData.isEmpty() != true) {
int maxWords = Utils.getMaxWords(tempData, fieldMeta)
currentFitData = StringUtils.getTextByWords(tempData, maxWords)
tempData = StringUtils.chopTextByWords(tempData, maxWords)
PDField field = fields.find{it.getFullyQualifiedName()[-1] == "$counter"}
field?.setValue(currentFitData)
counter++
}
} else {
PDField tempField = fields[0]
tempField.setValue(data)
}
}
}
}
The result is, in the first page, the field "Shipper" has a value of "David"
In the second page, the field "Shipper" is empty.
Here is an image. First page:
Second page:
What is the problem here?
UPDATE: I tried to add the widgets of every new acro form to the current page so that every field will a few kids widgets that will represent the field, but it still doesn't work.
// All the widgets that are associated with the fields
List<PDAnnotationWidget> widgets = acroForm.fields.collect {PDField field -> field.getWidgets().get(0)}
page.annotations.addAll(widgets)
UPDATE: I also tried to add the current widget of a field to the parent field's collection of widgets. Here is the code:
List<PDAnnotationWidget> widgets = []
// All the widgets that are associated with the fields
acroForm.fields.each {PDField field ->
PDAnnotationWidget widget = field.widgets.get(0)
// Adding the following widget to the page and to the field's list of annotation widgets
widgets.add(widget)
fields.find {it.getFullyQualifiedName() == field.getFullyQualifiedName()}?.widgets.add(widget)
}
page.annotations.addAll(widgets)
What you want is to have sereval visual representations of the same field. This is done by having several annotation widgets for such a field.
In PDF, when a field has only one annotation widget, they share a common dictionary. When it has several, the annotation widgets are in a child list of the field.
When you want several annotation widgets for one field, you need to create the annotation widgets with new PDAnnotationWidget() instead of calling field.getWidgets().get(0) and using that one. These widgets must be added to a list, and this list must be assigned to the field with setWidgets(). And for each widget you must call setRectangle() and setPage() and setParent().
An example for this is in the new CreateMultiWidgetsForm.java example. The setParent() method is not yet available in 2.0.3 (but will be in 2.0.4). In this answer, it is replaced with a call that does the same thing in a less elegant way.
public final class CreateMultiWidgetsForm
{
private CreateMultiWidgetsForm()
{
}
public static void main(String[] args) throws IOException
{
// Create a new document with 2 empty pages.
PDDocument document = new PDDocument();
PDPage page1 = new PDPage(PDRectangle.A4);
document.addPage(page1);
PDPage page2 = new PDPage(PDRectangle.A4);
document.addPage(page2);
// Adobe Acrobat uses Helvetica as a default font and
// stores that under the name '/Helv' in the resources dictionary
PDFont font = PDType1Font.HELVETICA;
PDResources resources = new PDResources();
resources.put(COSName.getPDFName("Helv"), font);
// Add a new AcroForm and add that to the document
PDAcroForm acroForm = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(acroForm);
// Add and set the resources and default appearance at the form level
acroForm.setDefaultResources(resources);
// Acrobat sets the font size on the form level to be
// auto sized as default. This is done by setting the font size to '0'
String defaultAppearanceString = "/Helv 0 Tf 0 g";
acroForm.setDefaultAppearance(defaultAppearanceString);
// Add a form field to the form.
PDTextField textBox = new PDTextField(acroForm);
textBox.setPartialName("SampleField");
// Acrobat sets the font size to 12 as default
// This is done by setting the font size to '12' on the
// field level.
// The text color is set to blue in this example.
// To use black, replace "0 0 1 rg" with "0 0 0 rg" or "0 g".
defaultAppearanceString = "/Helv 12 Tf 0 0 1 rg";
textBox.setDefaultAppearance(defaultAppearanceString);
// add the field to the AcroForm
acroForm.getFields().add(textBox);
// Specify 1st annotation associated with the field
PDAnnotationWidget widget1 = new PDAnnotationWidget();
PDRectangle rect = new PDRectangle(50, 750, 250, 50);
widget1.setRectangle(rect);
widget1.setPage(page1);
widget1.getCOSObject().setItem(COSName.PARENT, textBox);
// Specify 2nd annotation associated with the field
PDAnnotationWidget widget2 = new PDAnnotationWidget();
PDRectangle rect2 = new PDRectangle(200, 650, 100, 50);
widget2.setRectangle(rect2);
widget2.setPage(page2);
widget2.getCOSObject().setItem(COSName.PARENT, textBox);
// set green border and yellow background for 1st widget
// if you prefer defaults, just delete this code block
PDAppearanceCharacteristicsDictionary fieldAppearance1
= new PDAppearanceCharacteristicsDictionary(new COSDictionary());
fieldAppearance1.setBorderColour(new PDColor(new float[]{0,1,0}, PDDeviceRGB.INSTANCE));
fieldAppearance1.setBackground(new PDColor(new float[]{1,1,0}, PDDeviceRGB.INSTANCE));
widget1.setAppearanceCharacteristics(fieldAppearance1);
// set red border and green background for 2nd widget
// if you prefer defaults, just delete this code block
PDAppearanceCharacteristicsDictionary fieldAppearance2
= new PDAppearanceCharacteristicsDictionary(new COSDictionary());
fieldAppearance2.setBorderColour(new PDColor(new float[]{1,0,0}, PDDeviceRGB.INSTANCE));
fieldAppearance2.setBackground(new PDColor(new float[]{0,1,0}, PDDeviceRGB.INSTANCE));
widget2.setAppearanceCharacteristics(fieldAppearance2);
List <PDAnnotationWidget> widgets = new ArrayList<PDAnnotationWidget>();
widgets.add(widget1);
widgets.add(widget2);
textBox.setWidgets(widgets);
// make sure the annotations are visible on screen and paper
widget1.setPrinted(true);
widget2.setPrinted(true);
// Add the annotations to the pages
page1.getAnnotations().add(widget1);
page2.getAnnotations().add(widget2);
// set the field value
textBox.setValue("Sample field");
document.save("MultiWidgetsForm.pdf");
document.close();
}
}
I found createfishnet method in arcobject, but it doesn't work.Where is my mistake?
Geoprocessor gp = new Geoprocessor();
gp.OverwriteOutput = true;
ESRI.ArcGIS.DataManagementTools.CreateFishnet fishnet = new ESRI.ArcGIS.DataManagementTools.CreateFishnet();
fishnet.template = buffer_out;
//txtOutputPath2.Text="E:\\program\\shenzhen_science_committee\\sc\\landuse_subway\\shenzhen_subway\\23_net.shp"
fishnet.out_feature_class = txtOutputPath2.Text;
IFeatureCursor cursor1=buffer_out.Search(null,true);
IFeature buffer=cursor1.NextFeature();
IPoint centerPoint =new ESRI.ArcGIS.Geometry.Point();
IArea pArea = buffer.Shape as IArea;
pArea.QueryCentroid(centerPoint);
fishnet.origin_coord = centerPoint;
double height=0;
double width=0;
fishnet.cell_height = 0.1;
fishnet.cell_width = 0.1;
fishnet.number_columns = 50;
fishnet.number_rows = 50;
IGeoProcessorResult results = (IGeoProcessorResult)gp.Execute(fishnet, null);
The result shows wrong HRESULT E_FAIL.
I have tried this in ArcObjects with Java. What I found was that the fishnet could not be generated for area within a particular polygon, as in the ArcMap application. You would have to intersect or use spatial filter on the fishnet output.
Also, try giving all the parameters, even the optional ones like set corner coordinate. If you are using data in a particular projection system, that can be set to the output by setting the template (and this takes only Envelope).
Below is the code that I have used. I wanted the fishnet label as well, so I have enabled it. Make sure you use a space between the x and y coordinate of a point, entered as a String, which is probably the issue here.
GeoProcessor gp = new GeoProcessor();
gp.setOverwriteOutput(true);
IEnvelope aoi = buffer_out.getEnvelope();
CreateFishnet createFishnet = new CreateFishnet();
createFishnet.setOutFeatureClass(tempDir+"/"+fishnetOutput+".shp");
createFishnet.setTemplate(aoi);
createFishnet.setOriginCoord(aoi.getXMin()+" "+aoi.getYMin());
createFishnet.setYAxisCoord(aoi.getXMin()+" "+aoi.getYMax());
createFishnet.setCornerCoord(aoi.getXMax()+" "+aoi.getYMax());
createFishnet.setCellHeight(30.0);
createFishnet.setCellWidth(30.0);
createFishnet.setNumberRows(0);
createFishnet.setNumberColumns(0);
createFishnet.setLabels("LABELS");
createFishnet.setGeometryType("POLYLINE");
gp.execute(createFishnet, null);
I hope you can use this example and apply it to your code.