This is a modification of this question. I have an isometric grid of images and curious - is it possible to scroll it in free ways (diagonals included). Currently I have this code and it's possible to scroll 2D:
val scrollStateHorizontal = rememberScrollState()
val scrollStateVertical = rememberScrollState()
Box(
modifier = Modifier
.horizontalScroll(scrollStateHorizontal)
.verticalScroll(scrollStateVertical)
) {
for (i in 0..8) {
for (j in 0..7) {
val start = (y % 2 * 0.5 + x) * width
val top = i * height * 0.5
Image(modifier = Modifier.padding(start = start.dp, top = top.dp), painter = ...)
}
}
}
What is interesting:
Can I scroll diagonally?
How can I optimize it (memory consumption, etc.)? Maybe I should use LazyHorizontalGrid including LazyVerticalGrid/LazyColumn/LazyRow?
It seems, LazyHorizontalGrid can't be modified simply adding Modifier.verticalScroll. And it has a lag for first few seconds of scrolling (maybe for caching items) while simple Box scrolling acts smoothly from the start.
As of now, there's no official support for this, as far as I know. The only way you could implement this as of the current stable, is by using LazyLayout Composable, or by modifying the verticalScroll (or horizontal) Modifiers. Read here. It is a recent addition to the APIs so the documentation is very scarce. You'll have to look it up on the web for sample implementations.
"Read here"
Related
I have a tkinter interface with a few entry widgets as inputs. Upon clicking a button I would like those inputs to be sent to a separate script to be processed and a value printed and potentially returned back to the button (I am looking at this for a dual accuracy assessment statistic)
This is a lower scale example of what I have so far and am looking to accomplish
Example Secondary Script: GUI_ConnectorScript
def calculate():
global result
result = int(entry.get())
result += 1
print result
Primary Script: GUI_ConnectorScript
from Tkinter import *
import GUI_ConnectorScript
background = "#A8A8A8"
master = Tk()
screen_width = master.winfo_screenwidth()
screen_height = master.winfo_screenheight()
width = int(screen_width*0.7)
height = int(screen_height*0.7)
size = "%sx%s"%(width,height)
master.geometry(size)
master.title("GIS Display")
text = Text(master, width = 80, height = 40, background = background)
text.pack(expand = TRUE, fill = BOTH)
entry = Entry(master, width=5).place(x=100,y=100)
button = Button(master, text="Calculate", command=GUI_ConnectorScript).place(x=500,y=500)
mainloop()
I have been trying to figure this out for awhile and have look around a lot for an answer. I have found examples similar but I am having an issue getting it to work for my application.
I agree with Parviz, whenever GUI programs get too complicated you should use Object-Oriented Programming.
I can further advice that you use kivy (if possible) instead of tkinter, its much better for bigger projects
I am looking for firefox addon api to take screenshot of visible area of document.
Chrome and Safari have api's to achieve this. And they are pretty fast.
I could not find anything specific for firefox.
I found a workaround at How do I use the canvas drawWindow function in an addon created using the addon sdk? but this solution takes full page screenshot with scrolls including (hidden parts of document). There are 2 issues for this solution;
1- if page has long scroll, it takes long time to complete screenshot process. Because it is using canvas based drawing.
2- I would like to get screenshot of visible area of document, not whole document.
Is there any workaround for this?
Thanks.
Using the SDK you can do something like this:
const { window: { document } } = require('sdk/addon/window');
const { getTabContentWindow, getActiveTab } = require('sdk/tabs/utils');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
const canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
document.documentElement.appendChild(canvas);
function captureTab(tab=getActiveTab(getMostRecentBrowserWindow())) {
let contentWindow = getTabContentWindow(tab);
let w = contentWindow.innerWidth;
let h = contentWindow.innerHeight;
let x = contentWindow.scrollX;
let y = contentWindow.scrollY;
canvas.width = w;
canvas.height = h;
let ctx = canvas.getContext('2d');
ctx.drawWindow(contentWindow, x, y, w, h, '#000');
return canvas.toDataURL();
}
That should takes only the visible area. By default, it grabs the active tab, but you can pass any other tab – because is designed as low level API it takes a native tab, however, not a SDK tab.
You can put in a module and exports just the captureTab function.
Edit: e10s version
The code above is not currently compatible with Firefox with e10s available, as Ian Bicking noted in the comment. An easy way to workaround this issue, is create a temporary canvas in the same document and content process we want to capture the screenshot:
const { getTabContentWindow, getActiveTab } = require('sdk/tabs/utils');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
function captureTab(tab=getActiveTab(getMostRecentBrowserWindow())) {
let contentWindow = getTabContentWindow(tab);
let { document } = contentWindow;
let w = contentWindow.innerWidth;
let h = contentWindow.innerHeight;
let x = contentWindow.scrollX;
let y = contentWindow.scrollY;
let canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
canvas.width = w;
canvas.height = h;
let ctx = canvas.getContext('2d');
ctx.drawWindow(contentWindow, x, y, w, h, '#000');
let dataURL = canvas.toDataURL();
canvas = null;
return dataURL;
}
That works in both e10s and no-e10s FF version; the downside comparing to the previous one is creating a canvas every time we want to take a screenshot, but I think is acceptable.
Your assumption that taking a screenshot on Firefox with canvas is somehow slow is wrong.
I did a couple of screenshots and Firefox/canvas was faster than Chrome/captureVisibleTab.
Actually Firefox is better suited for as-fast-as-possible screenshots, since its canvas expose to privileged code the mozFetchAsStream method, allowing to bypass the actual bottleneck which is the base64 encoding of the image data.
Some numbers
Chrome: captureVisibleTab 200-205ms
Firefox: drawImage 20-25ms + toDataURL 125-130ms
The devtools screenshot command is a good example of how to capture just the visible part
In all fairness, to make a meaningful comparison one has to take into account whether Chrome's PNG encoder favors compression over speed. Still, this doesn't change the fact that Firefox's canvas is fine.
edit: OK, that base64 encoding remark is dumb, I don't know what I was thinking. Perhaps what I should write instead is that Firefox's canvas is not only fast but also versatile.
I'm trying to create maps application like the WP7 Maps. I know that in WPF it's simple to manage map canvases gestures through MatrixTransform, but WP7's version of MatrixTransform is less functional.
Is there any patterns how to manage all ManipulationDelta events to:
Zoom in and zoom out. Now I make it like that:
var maxScale = Math.Max(
args.DeltaManipulation.Scale.X,
args.DeltaManipulation.Scale.Y);
if (Math.Abs(maxScale - 0) > 0.0001 &&
((maxScale < 1 && _scale.ScaleX > MIN_SCALE) ||
(maxScale > 1 && _scale.ScaleX < MAX_SCALE)))
{
_scale.ScaleX *= maxScale;
_scale.ScaleY *= maxScale;
}
where _scale = new ScaleTransform(); and it has to be improved to manage position of canvas
Move map by finger. By first step it's look like:
_translation.X += args.DeltaManipulation.Translation.X
* _scale.ScaleX;
_translation.Y += args.DeltaManipulation.Translation.Y
* _scale.ScaleX;
where _translation = new TranslateTransform();
Make some dynamic after Pan, Pinch and Stretch
no current implementation, but I'm looking at ManipulationCompleted, where add some code to "continue" gestures in more natural way.
I'm looking for typical solution to manage this features, may be my way is wrong and not through ManipulationDelta
After a little research I've decided to use this behaviour to add multitouch http://gallery.expression.microsoft.com/MultiTouch/
If something goes wrong I can just see at reflected code and create something like that
I had created a HorizontalFieldManager & added BitmapFields in that.
In Blackberry Storm, Display.getWidth() is 480. In that I want to use first 450 to add some BitmapFields at LHS of screen which I m creating at runtime & add 2 BitmapFields at start at RHS of Screen.
2 BimapFields which I want to show at start r added in Constructor & other BitmapFields which I m creating at run time r added afterwords like..
class MyCanvas extends MainScreen
{
MyCanvas()
{
hfm_BitmapField = new HorizontalFieldManager(){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(maxWidth, maxHeight);
setExtent(Display.getWidth()-30, 60);
}
};
startBitmap = Bitmap.getBitmapResource("start.png");
startBitmapField = new BitmapField(startBitmap, BitmapField.ACTION_INVOKE | BitmapField.FIELD_HCENTER | BitmapField.FIELD_RIGHT);
hfm_BitmapField.add(startBitmapField);
endBitmap = Bitmap.getBitmapResource("end.png");
endBitmapField = new BitmapField(endBitmap, BitmapField.ACTION_INVOKE | BitmapField.FIELD_HCENTER | BitmapField.FIELD_RIGHT);
hfm_BitmapField.add(endBitmapField);
drawBitmap();
}
public void drawBitmap()
{
bitmap[i] = new Bitmap(50, 50);
Graphics g = new Graphics(bitmap[i]);
g.drawLine(5,5,25,25);
bitmapField[i] = new BitmapField(bitmap[i]);
synchronized(UiApplication.getEventLock()) { hfm.add(bitmapField[i]); }
}
I want startBitmapField & endBitmapField at RHS & bitmapField[i] which I m creating at runtime at LHS of HorizontalFieldManagers.
I m thinking to add 2 HorizontalFieldManagers. 1 for bitmapField[i] & 1 for startBitmapField & endBitmapField. But how to add 2 HorizontalFieldManagers or any other FieldManagers in a row?
Any solution? How to do it?
You can put the 2 horizontal field managers inside another HorizontalFieldManager.
Rather than use the alignment flags try adding to your sublayout method.
For each child of your Manager (hfm) you need to call setPositionChild. So if you want it right aligned and vertically centred you would do something like:
setPositionChild(deleteButton, hfm.getPreferredWidth() - deleteButton.getPreferredWidth(), (hfm.getPreferredHeight() / 2) - (deleteButton.getPreferredHeight() / 2));
This would set the top left hand corner of the delete button to be at the correct position such that it is right aligned and vertically centred within the hfm.
There is going to be a problem if you see the application in touch. You must have each of your customized field in a separate field manager to avoid using touch event. If you use layoutChild instead of super.sublayout(width,height), this will disable the navigation in the screen, so avoid using it. Use navigationMovement to customize your navigation of your fields. More: If you do not use super.sublayout function, it might not layout some of your fields, hence it is recommended that you use it.
More: use Storm emulator for all your touch based application, and 4.5 Pearl emulator JDEs for all the other releases, for the compatibility issues.
Scenario
In a screen I have 2 managers: 1) menu manager at the top and 2) body manager that has info/button elements. The menu manager does custom drawing so that its menu elements (LabelFields) are properly spaced.
Core Issue - Manager and subfield drawing order
The screen draws fine except when the user preforms an action (clicks a button) that results in an element withing the body manager being added/removed. Once field elements are added/removed from the body, the order in which the menu is drawn gets mixed up.
When the body manager adds or removes a field, instead of the menu manager drawing itself and then its sub elements (label fields), the menu manager begins to draw its sub elements and then itself; thus painting on top of the label fields and making them look like they've disappeared.
Comments
Already tried invalidate and other options -- I've tried to call invalidate, invalidateall, updateDisplay... after adding/removing field elements from body. All without success.
Removing custom sublayout works -- The only way that I can resolve this issue is to remove the menu managers custom sublayout logic. Unfortunately the menu system then draws in a traditional manner and does not provide enough spacing.
Below is the sublayout code for the menu manager, am I missing something here?
public void sublayout(int iWidth, int iHeight)
{
final int iNumFields = getFieldCount();
int maxHeight = 0;
final int segmentWidth = iWidth / iNumFields;
final int segmentWidthHalf = segmentWidth / 2;
for (int i = 0; i < iNumFields; i++)
{
final Item currentField = (Item)this.getField(i);
// 1. Use index to compute bounds of the field
final int xSegmentTrueCenter = segmentWidth * i + segmentWidthHalf;
// 2. center field inbetween bounds using field width (find fill width of text)
final int xFieldStart = xSegmentTrueCenter - currentField.getFont().getAdvance(currentField.getText())/2;
// set up position
setPositionChild(currentField, xFieldStart, getContentTop() + MenuAbstract.PADDING_VERTICAL);
// allow child to draw itself
layoutChild(currentField, iWidth, currentField.getHeight());
// compute max height of the field
//int fieldheight = currentField.getHeight();
maxHeight = currentField.getHeight() > maxHeight
? currentField.getHeight() + 2 * MenuAbstract.PADDING_VERTICAL
: maxHeight;
}
this.setExtent(iWidth, maxHeight);
}
Final Questions
Ultimately I want to keep the custom layout of the menu manager while being allowed to redraw field elements. Here are my final questions:
Have you experienced this before?
Why would the menu manager begin drawing in the wrong order when a field element is added/remove to the screen?
Does the native Manager.sublayout() do something that I'm not to maintain drawing order?
I haven't seen the behavior you describe, but the following line is a little troubling:
// allow child to draw itself
layoutChild(currentField, iWidth, currentField.getHeight());
getHeight() shouldn't return a sensible value until the field has had setExtent called through the layoutChild method. Though I'd expect that it would cause problems in all cases - not sure why this would work the first time around. In your logic I think you can safely just use iHeight instead of currentField.getHeight() in that line. The field will only make itself as big as it needs to be - it won't use all of iHeight unless it's something like a VerticalFieldManager