Hiding / showing markers: OSMDroid / OpenMaps - osmdroid

I have an app which uses or googlemaps or openMaps (offline) depending of connection state.
In each case there are markers, for places or point of interest or… I want that the user can display or hide some category of markers.
When using google maps I have a menu and in the action bar when some item is selected it toggles between showing or hiding the markers from the correpondent category; As for google maps that works easily & perfectly using isVisible();
As for osmdroid i have not found in the doc any equivalent to isVisible(), neither any show() or hide() method. So I have tried to use as a workaround somemarkers.getAlpha() & somemarkers.setAlpha(), toggling between 0 & 1 alpha values.
No error occurs but the visibility of markers remains the same, not toggling, or only randomly when i tap 10 or 20 times on the action icon.
In the log i get "InputEventReceiver: Attempted to finish an input event but the input event receiver has already been disposed" which seems to me to be the cause.
But what to do to avoid this?
KitKat, SonyXperia Z

In osmdroid, the method to hide/show overlays (markers) is:
Overlay.setEnabled(boolean enabled)

I have done this bit differently.
Extend ItemizedIconOverlay
Add as an overlay to mapView
Hide markers by using removeAllItems or removeItem
Show marker by adding it to the itemized overlay list
Create a new Overlay class by extending ItemizedIconOverlay.
Note: WaypointOverlayItem extends OverlayItem. {It's your custom overlay model class}
public class NavigatorItemizedOverlay extends ItemizedIconOverlay<WaypointOverlayItem> {
private Context mContext;
public NavigatorItemizedOverlay(final Context context, final List<WaypointOverlayItem> aList) {
super(context, aList, new OnItemGestureListener<WaypointOverlayItem>() {
#Override
public boolean onItemSingleTapUp(int index, WaypointOverlayItem item) {
return false;
}
#Override
public boolean onItemLongPress(int index, WaypointOverlayItem item) {
return false;
}
});
// TODO Auto-generated constructor stub
mContext = context;
}
}
Add this Overlay to your map
//Add Itemized overlay
navigatorItemizedOverlay = new NavigatorItemizedOverlay(getActivity(), waypointOverlayItemList);
mapView.getOverlays().add(navigatorItemizedOverlay);
To Add marker:
navigatorItemizedOverlay.addItem(waypointOverlayItem);
To hide all markers:
navigatorItemizedOverlay.removeAllItems();
There are other methods:
removeItem(position) and removeItem(waypointOverlayItem)

Related

How to not break bindings in qml?

I currently have an image which becomes visible or not depending on some steps of a process. The qml code for that image is the following :
Image
{
id : cameraDisplay
visible : mainViewModel.getCurrentSegmentIsCameraDisplayed
anchors.centerIn : parent
source: "Images/Todo.png"
}
I also have a button, which the user can press to display that image or not :
Button
{
Layout.fillWidth: true
Layout.fillHeight: true
buttonText : "CAMERA"
onClicked: {cameraDisplay.visible = !cameraDisplay.visible;}
}
In the c++, the binding looks like this :
Q_PROPERTY(bool getCurrentSegmentIsCameraDisplayed
READ getCurrentSegmentIsCameraDisplayed
NOTIFY segmentChanged)
the idea is that every time the current step of the process changes in my program, a notification is sent. That notification is then sent to the QML, which then gets the backend value to know if the camera should display or not that image.
I also have a button, which allows the user to toggle on or off the visibility of that image. The problem is that once that button is clicked, I lose the Q_PROPERTY binding, which means that once I go to the next segment, the notifications sent to the qml won't change the visibility of the image.
So basically, what I would want would be the following situation :
The segment changes, a notification is sent to the qml, and the visiblity of the image is updated automatically.
The user presses the button, which toggles the visibility of that image.
The segment changes again, a notification is sent to the qml, and the visibility of that image is again updated according to the backend.
Currently, step 3 doesn't work. What should I change to make it work?
thanks
You can change your binding in C++ to emit a signal when a change occurs, like this:
Q_PROPERTY(bool getCurrentSegmentIsCameraDisplayed
READ getCurrentSegmentIsCameraDisplayed
WRITE setCurrentSegment
NOTIFY segmentChanged)
In your class.h,
class MyClass : public QObject
{
Q_OBJECT
bool _segment;
public:
const bool &getCurrentSegmentIsCameraDisplayed() const;
public slots:
void setCurrentSegment(const bool &newSegment);
signals:
void segmentChanged(const bool &segment);
};
In your class.cpp,
void MyClass::setCurrentSegment(const bool &newSegment)
{
if (_segment == newSegment){
return;
}else{
_segment = newSegment;
emit segmentChanged(_segment);
}
}
const bool &MyClass::getCurrentSegmentIsCameraDisplayed() const
{
return _segment;
}
Now in C++ you can change the process value any way you want. On the QML side, when you need to change the property, just use the SLOT setCurrentSegment passing its new state:
Image
{
id : cameraDisplay
visible: mainViewModel.getCurrentSegmentIsCameraDisplayed
anchors.centerIn : parent
source: "https://www.cleverfiles.com/howto/wp-content/uploads/2018/03/minion.jpg"
}
Button
{
text : "CAMERA"
onClicked: {
mainViewModel.setCurrentSegment(!cameraDisplay.visible)
}
}
The binding is maintained regardless of where the change takes place.
I think you don't want your Button to directly change the visibility. You want it to change some other flag that the visibility depends on. How about something like this:
property bool showImage: true
Image
{
id : cameraDisplay
visible : showImage && mainViewModel.getCurrentSegmentIsCameraDisplayed
}
Button
{
onClicked: {showImage = !showImage}
}

Is Qml able to receive a list of models and let listview to choose which one to use?

I have got one listview in qml now known as listview1. For each element in listview1, it contains another listview used to show some of its variables. Now I want to make it possible for all such sub-listviews able to add items to them. And also adding item to one of them will not affect all the other listviews in other elements of listview1.
What is the best way to solve such problem? Thanks
Adapted from https://stackoverflow.com/a/55604525/1493608 (same thing but with a GridView instead of a ListView) :
Give each sub-ListView a UUID.
Connect each sub-ListView to a listview1 signal that you will use to broadcast to sub-ListView delegates what you will want to do.
In this signal, put your UUID.
In sub-ListView receivers, put a filter on the UUID and do what you want to do only if it is the right one.
ListView {
id: listview1
signal broadcaster(string uuid, var other_args)
delegate: ListView {
// Provided like this or as a role from the corresponding list element
property string uuid: ""
signal sendToOtherLV(string uuid, var other_args)
function lv_receiver(broadcasted_uuid, other_args) {
if (this.uuid === broadcasted_uuid) {
// Do what you have to do with other_args.
}
}
Component.onCompleted: {
/*
* Custom way to generate the UUID and store it so
* the other ListViews will be able to retrieve it.
*/
this.uuid = generateAndStoreUUID()
// Connecting the sub-ListView to your "sub-ListView LAN".
this.sendToOtherLV.connect(listview1.broadcaster)
listview1.broadcaster.connect(this.lv_receiver)
}
Component.onDestruction: {
// Disconnecting the sub-ListView from your "sub-ListView LAN".
this.sendToOtherLV.disconnect(listview1.broadcaster)
listview1.broadcaster.disconnect(this.lv_receiver)
}
// Here is an example of what you might have to do
function foo() {
// ...
var otherlv_receiver_uuid
var signal_args
// Retreive the UUID of the ListView that you want to send something to.
// Set the other arguments you want to send through the signal.
this.sendToOtherLV(otherlv_receiver_uuid, signal_args)
// ...
}
// Other sub-ListView-related stuff
}
// Other listview1-related stuff
}

Override open variable for class in Swift and SpriteKit for use in XCode's ActionEditor

I'm trying to make small platformer game, just in learning purposes. I've tried to animate character with array of SKTextures like this:
let animation: SKAction = SKAction.animate(
with: frames.map {
let texture : SKTexture = SKTexture(imageNamed: $0)
texture.filteringMode = SKTextureFilteringMode.nearest
return texture
},
timePerFrame: 0.15
)
frames variable is array of SKTextures. I've used map to set filtering mode for each texture. This works fine and dandy, but than i've discovered that i can create animations (actions) in ActionEditor in XCode with AnimateWithTextures action. And here lies my problem. This is much more efficient, but i can't change filtering mode for textures in animation in ActionEditor. I've looked into SKTexture class and saw this:
open class SKTexture : NSObject, NSCopying, NSCoding {
...
/**
The filtering mode the texture should use when not drawn at native size. Defaults to SKTextureFilteringLinear.
*/
open var filteringMode: SKTextureFilteringMode
...
}
If i'm not mistaken open means that i can override variable, but i don't know how. I want to set default value of filteringMode to SKTextureFilteringMode.nearest for all SKTextures so ActionEditor will use textures with texture filtering set to nearest neighbor.
Also if you know how to set filtering mode for textures in specific action – i would like to know how to do it too. Thanks
you can create a function to setup the animation for you, and create an extension to SKTexture with your custom init, and when your ready just call it to your node.
extension SKTexture { // Declare this extension outside your class decleration
convenience init(customImageNamed: String) {
self.init(imageNamed: customImageNamed)
self.filteringMode = .nearest
}
}
func setupAnimationWithPrefix(_ prefix: String, start: Int, end: Int, timePerFrame: TimeInterval) -> SKAction{
var textures = [SKTexture]()
for i in start...end{
textures.append(SKTexture(customImageNamed: "\(prefix)\(i)"))
}
return SKAction.animate(with: textures, timePerFrame: timePerFrame)
}
if you have 10 images named image1, image2, image3 ect..then this is how you would use this function
func runAction(){
let action = setupAnimationWithPrefix("image", start: 1, end: 10, timePerFrame: 0.1)
yourNode.run(action)
} // you can change timePerFrame to your liking i find 0.1 sec per frame the best
Unfortunately you can't override a variable without subclassing it, that is to do something like
class MyTexture: SKTexture {
from there, you could override the variable:
override var filteringMode: SKTextureFilteringMode {
get {
return .nearest
}
set {
}
}
That should work, but now you can't change the filtering mode, ever (without going through a bunch of hooplah).
So the more apt way would be to set the default value via the initializer, but SKTexture has no public designated initializers, so that option is out of the window.
So your best bet is going to be the convenience init extension by Arie, or just make a plain function that returns a new texture:
func nearestTexture(imageNamed name: String) -> SKTexture {
let newTex = SKTexture(imageNamed: name)
newTex.filteringMode = .nearest
return newTex
}
let texture: SKTexture = nearestTexture(imageNamed: "lol")
ActionEditor is still very limited in features, you are going to have to write some kind of code behind to allow for texture filtering. If you do not plan on scaling your sprites (Note I said sprite, not scene, these are two different behaviors), then I would not even worry about texture filtering, the time difference would be negligible.

WICKET: Updating a self-made Panel

ive got the following Problem:
my self-made video-class (extending Panel) doesnt get updated, if its model changes.
Thats the current state:
I got a Class "A" with a ListChoice. This Class creates the Panel "descrPanel", which gets a Model, containing the current selected Item of the ListChoice. It is updated, when the User selects something in the ListChoice (The ListChoice got an AjaxBehaviour, updating the descrPanel via target.add(descrPanel)):
Class A:
PropertyModel<Exercise> currExerciseModel = new PropertyModel<Exercise>(this,"selectedExercise");
final ExerciseDescriptionPanel descrPanel = new ExerciseDescriptionPanel("descrPanelTag", currExerciseModel);
descrPanel.setOutputMarkupId(true);
In Class ExerciseDescriptionPanel, i inserted my self-made Video-Class (extending Panel). Also i inserted a MultiLineLabel:
Class ExerciseDescriptionPanel
public class ExerciseDescriptionPanel extends Panel {
private IModel<Exercise> model;
private Exercise exercise;
public ExerciseDescriptionPanel(String id, IModel<Exercise> model) {
super(id, model);
this.model = model;
MultiLineLabel mll = new MultiLineLabel("mll", new Model() {
#Override
public String getObject() {
if (ExerciseDescriptionPanel.this.getModel().getObject() != null){
return ExerciseDescriptionPanel.this.getModel().getObject().getDescription();
}
else return "";
}
});
add(mll);
Video video = new Video("myVideo", new Model<Exercise>(){
#Override
public Exercise getObject() {
if (ExerciseDescriptionPanel.this.getModel().getObject() != null){
return ExerciseDescriptionPanel.this.getModel().getObject();
}
else return new Exercise();
}
});
add(video);
}
Well, what i dont understand is: While the Description is updated based on the current selection of the ListChoice, the Video-Class just ignores it and keeps returning the "new Exercise()", which schould only be returned at the first load of the ListChoice, when no selection is made.
I also provide you the Video-Class:
Class Video
public class Video extends Panel{
private IModel<Exercise> model;
public Video(String id, IModel<Exercise> model) {
super(id, model);
String src = ((Exercise)model.getObject()).getVideo();
String startPicDest = ((Exercise)model.getObject()).getPicture();
WebMarkupContainer flashSrc = new WebMarkupContainer("flashSrcTag");
flashSrc.add(new AttributeModifier("value", "config={'playlist':['" +
startPicDest +"',{'url':'"+ src +"','autoPlay':false}]}"));
this.add(flashSrc);
setOutputMarkupId(true);
}
}
Ive been searching through the internet for hours now, without finding anything helpful.
Hope you guys are able to give me some solution to this problem. Thanks in regard.
Greetings
You're pulling the exercise out of the model once only:
public Video(String id, IModel<Exercise> model) {
super(id, model);
String src = ((Exercise)model.getObject()).getVideo();
...
}
How is this supposed to be up-to-date when the exercise changes later on?
You have to get the actual value for each render:
WebMarkupContainer flashSrc = new WebMarkupContainer("flashSrcTag") {
public void onComponentTag(ComponentTag tag) {
Exercise temp = (Exercise)model.getObject();
String src = temp.getVideo();
String startPicDest = temp.getPicture();
tag.put("value", String.format("config={'playlist':['%s',{'url':'%s','autoPlay':false}]}", startPicDest, src));
}
};
NOTE: Please ignore this humble try to help you, svenmeier's answer is way better than mine.
I'm not 100% sure if this is true, but could it be related to the difference between your Video being a MarkupContainer and the MultiLineLabel being a WebComponent?
Both the Video and the MultiLineLabel are added to the ExerciseDescriptionPanel in its constructor. If I understand the Wicket documentation correctly, as long as the surrounding Page and thus the ExerciseDescriptionPanel stay the same instance, the markup of the Video will not be regenerated. It says:
A Page renders itself by rendering its associated markup (the html file that sits next to the Page). As MarkupContainer (the superclass for Page) iterates through the markup stream for the associated markup, it looks up components attached to the tags in the markup by id. Since the MarkupContainer (in this case a Page) is already constructed and initialized by onBeginRequest(), the child for each tag should be available in the container. Once the Component is retrieved, it's render() method is called.
Maybe you calling modelChanged() on your Video once you change the Model of your ExerciseDescriptionPanel could indicate that the markup has to be refreshed.

LWUIT List works terribly slow

I've faced with the well-known problem in LWUIT. My list component with the checkbox renderer scrolls very slow. If to test my application on emulator it runs quite smoothly (nevertheless I see CPU utilization splashes up to 60% during scroll action), but if to run it on mobile phone it takes a couple of seconds between focus movements.
There's a code of renderer:
public class CheckBoxMultiselectRenderer extends CheckBox implements ListCellRenderer {
public CheckBoxMultiselectRenderer() {
super("");
}
//override
public void repaint() {
}
public Component getListCellRendererComponent(List list, Object value,
int index,boolean isSelected) {
Location loc = (Location)value;
setText(loc.getLocationName());
setFocus(isSelected);
setSelected(loc.isSelected());
return this;
}
public Component getListFocusComponent(List list) {
setText("");
setFocus(true);
getStyle().setBgTransparency(Consts.BG_TRANSPARENCY);
return this;
}
}
that's the code of my form containing the list:
protected void createMarkup() {
Form form = getForm();
form.setLayout(new BorderLayout());
form.setScrollable(false);
Label title = new Label("Choose location zone:");
title.getStyle().setMargin(5, 5, 0, 0);
title.getStyle().setBgTransparency(Consts.BG_TRANSPARENCY);
title.setAlignment(Component.CENTER);
form.addComponent(BorderLayout.NORTH, title);
list = new List(StateKeeper.getLocationsAsList());
list.setFixedSelection(List.FIXED_NONE_CYCLIC);
// list.setSmoothScrolling(true);
list.getStyle().setBgTransparency(0);
list.setListCellRenderer(new CheckBoxMultiselectRenderer());
list.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
// List l = (List)ae.getSource();
// l.requestFocus();
// l.setHandlesInput(true);
Location selItem = (Location)list.getSelectedItem();
selItem.setSelected(!selItem.isSelected());
}
});
form.addComponent(BorderLayout.CENTER, list);
}
I would be very thankful for any help!
We must be so carefull building lwuit List. If we have made something wrong they can work worse than expected. I recommend you to take a look on this
LWUIT Blog ListRender
You can also rewrite your paint method. You list's speed will be increased.