fyne-io / fyne

Cross platform GUI toolkit in Go inspired by Material Design
https://fyne.io/
Other
25.27k stars 1.4k forks source link

The mouse enter button will trigger the ChildUIDs of the tree, but the button has nothing to do with the tree #2655

Closed Thepatterraining closed 3 years ago

Thepatterraining commented 3 years ago

Describe the bug:

I have a button and a tree. When I move the mouse to the position of the button, the ChildUIDs of the tree will be triggered

To Reproduce:

Steps to reproduce the behaviour:

  1. Create a tree and a button
  2. ChildUIDs that implement the tree
  3. Use NewBorderLayout layout to place trees and buttons
  4. run go run main.go

Screenshots:

image As shown in the figure, placing it on any button will trigger the ChildUIDs of the tree image

Example code:

package main
import "fyne.io/fyne/v2/widget"
var tree *widget.Tree
func main(){
myApp := app.New()
window := myApp.NewWindow("Box Layout")
tree = widget.NewTree(nil, nil, nil, nil)
tree .ChildUIDs = func(uid widget.TreeNodeID) (c []widget.TreeNodeID) {
        fmt.Println("tree childUIDS ...")
        if uid == root {
            c = fileTree.getFileList(uid)
        } else {
            treeNode := fileTree.nodes[uid]
            c = fileTree.getFileList(treeNode.GetPath())
        }
        return
    }
topBtn := widget.NewButton("show local dir", func() {
        fmt.Println("clicked show btn")
})
borderLayout := layout.NewBorderLayout(topBtn, nil, tree, nil)
containerCtx := container.New(borderLayout, topBtn, tree)
window.SetContent(containerCtx)
window.Resize(fyne.NewSize(1000, 1000))
window.ShowAndRun()
}

Device (please complete the following information):

andydotxyz commented 3 years ago

The code you have posted unfortunately does not compile. I tried adapting it to work but the tree wasn't visible so I could not replicate the issue.

the ChildUIDs of the tree will be triggered

You know that this is just a data lookup though right? It is not any kind of "user interaction" callback. For that you would use OnSelected.

Thepatterraining commented 3 years ago

sorry, I revised the code and screenshots image When the mouse is placed on the button, the ChildUID of the tree will be triggered

code

package main

import (
    "fmt"
    "os"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/layout"
    "fyne.io/fyne/v2/theme"
    "fyne.io/fyne/v2/widget"
)

var tree *widget.Tree

func main() {
    fmt.Println("开始啦....")
    myApp := app.New()
    fmt.Println(myApp)
    myWindow := myApp.NewWindow("Box Layout")
    // filetree.DirTree(myWindow)
    tree = widget.NewTree(nil, nil, nil, nil)
    root := "/home/zt/go/goFile"
    tree.ChildUIDs = func(uid widget.TreeNodeID) (c []widget.TreeNodeID) {
        fmt.Println("tree childUIDS ...", uid)
        if uid == root {
            c = getFileList(uid)
        } else {
            c = getFileList(root)
        }
        return
    }
    tree.CreateNode = func(branch bool) (o fyne.CanvasObject) {
        // label :=
        var icon fyne.CanvasObject
        if branch {
            icon = widget.NewIcon(nil)
        } else {
            icon = widget.NewFileIcon(nil)
        }
        fmt.Println("创建node", branch)
        return container.NewHBox(icon, widget.NewLabel("123"))
        // return widget.NewLabel("123")
    }
    tree.UpdateNode = func(uid widget.TreeNodeID, branch bool, node fyne.CanvasObject) {
        // lbl := node.(*widget.Label)
        // lbl.(*widget.Icon).SetResource(r)
        // lbl.SetText("dir or file" + uid)
        c := node.(*fyne.Container)
        fmt.Println("=======", uid, branch)
        if branch {
            var r fyne.Resource
            if tree.IsBranchOpen(uid) {
                // Set open folder icon
                r = theme.FolderOpenIcon()
            } else {
                // Set folder icon
                r = theme.FolderIcon()
            }
            c.Objects[0].(*widget.Icon).SetResource(r)
        } else {
            // filePath := fileTree.nodes[uid].filePath
            // c.Objects[0].(*widget.FileIcon).SetURI(storage.NewFileURI(filePath))
        }
        c.Objects[1].(*widget.Label).SetText(uid)
    }
    tree.IsBranch = func(uid widget.TreeNodeID) (ok bool) {
        return true
    }
    topBtn := widget.NewButton("show local dir", func() {
        fmt.Println("clicked show btn")
    })
    borderLayout := layout.NewBorderLayout(topBtn, nil, nil, nil)
    containerCtx := container.New(borderLayout, topBtn, tree)
    myWindow.SetContent(containerCtx)
    myWindow.Resize(fyne.NewSize(1000, 1000))
    myWindow.ShowAndRun()
}

func getFileList(path string) (fileList []string) {
    fmt.Println("path:", path)
    fi2, err := os.ReadDir(path)
    if err != nil {
        panic("panic:fileTree:" + err.Error())
    }
    for _, file := range fi2 {
        fileList = append(fileList, file.Name())
    }
    return
}

Yes, the ChildUID of the tree is just a data search, but when the mouse moves over the button, the ChildUID of the tree will be triggered, which will cause the tree to be reset. I feel that when the mouse moves into the button, nothing in the tree should be triggered. Because I want to implement an input box to enter the file directory and click the button to display the files in the file directory on the tree, but when I display it on the tree, because the mouse is on the button, the tree’s ChildUID is triggered, which causes the tree to reset back.

andydotxyz commented 3 years ago

Thanks for explaining this - I now have the test case running

However it does not week to work well - I am getting recursive lookups in your file handling code.

which will cause the tree to be reset

This is worrying. Data access should not cause the UI to reset - I think there is an error in your code somewhere. So far I have not found a bug in Fyne. We need to look up the UID list for things like app layout so there is no guarantee that it is only called on change...

In essince your if uid == root is a false comparison - the root UID will be "" with your setup, if you fix this then your root lookups may start working corretly. Then if you look into your if further you will see that both branches run the same code.

Please fix the errors in your logic and see if the errors go away. If you would like an existing file tree component consider using https://github.com/fyne-io/fyne-x/blob/master/widget/filetree.go instead.

Thepatterraining commented 3 years ago

Yes,I already try used https://github.com/fyne-io/fyne-x/blob/master/widget/filetree.go. But it has the same problem. These are code.I hope clicked this button show folder of /home/zt/go/goFile on the tree.But nothing happened.

package main

import (
    "fmt"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/layout"
    "fyne.io/fyne/v2/storage"
    "fyne.io/fyne/v2/widget"
    widgetx "fyne.io/x/fyne/widget"
)

var tree *widgetx.FileTree

func main() {
    fmt.Println("开始啦....")
    myApp := app.New()
    fmt.Println(myApp)
    myWindow := myApp.NewWindow("Box Layout")
    tree = widgetx.NewFileTree(storage.NewFileURI("/home/zt/go"))
    topBtn := widget.NewButton("show local dir", func() {
        fmt.Println("clicked show btn")
        tree = widgetx.NewFileTree(storage.NewFileURI("/home/zt/go/goFile"))
    })
    borderLayout := layout.NewBorderLayout(topBtn, nil, nil, nil)
    containerCtx := container.New(borderLayout, topBtn, tree)
    myWindow.SetContent(containerCtx)
    myWindow.Resize(fyne.NewSize(1000, 1000))
    myWindow.ShowAndRun()
}
andydotxyz commented 3 years ago

Yes,I already try used https://github.com/fyne-io/fyne-x/blob/master/widget/filetree.go. But it has the same problem.

Can I just re-iterate that Fyne calling 'ChildUIDs' callback is not any indication that the user has selected that item. I still don't understand what bug is being reported here.

andydotxyz commented 3 years ago

In the code above setting a new 'FileTree' to the 'tree' variable does nothing. You have not added it to the object tree or in any way asked for it to be rendered. Consider 'Tree.SetLocation' instead.

Thepatterraining commented 3 years ago

Oh! Yes, thank you. I re-rendered the tree variable, which solved my problem. I thought I changed this tree variable and it will re-render automatically. But is it too troublesome to re-render each time? Is there an automatic rendering solution? I tried to use data binding, but the map[string]interface{} type created by binding.NewUntypedMap(), the function widget.NewTreeWithStrings cannot be used. I don’t know what you said about 'Tree.SetLocation' Can this problem be solved? Where should I find it, I did not find it in the https://developer.fyne.io/api/v2.1/ document, in fyne.io/fyne/v2/widget/tree.go It is also not found in the file.

there are codes

        treeData := binding.NewUntypedMap()
    treeData .SetValue("go", []string{"goFile", "gobee"})
    treeDataValue , err := msb.Get()
    if err != nil {
        fmt.Println("error", err)
    }
    ms := treeDataValue.(map[string][]string)
    newTree = widget.NewTreeWithStrings(ms)
andydotxyz commented 3 years ago

I thought I changed this tree variable and it will re-render automatically.

The new item you set to the variable replaces the old one. The old one was in the visible list of objects, when you change a variable reference it does not replace the content inside the object graph. You need to tell the container to replace the old item with a new one.

But is it too troublesome to re-render each time? Is there an automatic rendering solution?

This is not a rendering problem, the issue is that your code does not tell the container to replace the content. If you want to replace an old object with a new one regularly it may be easiest to wrap it in container.NewMax and then you can just set the Content whenever you want it to change.

I don’t know what you said about 'Tree.SetLocation' Can this problem be solved?

My apologies, I thought that had been implemented on the file tree widget in fyne-x, it seems we missed that. Feel free to open an issue or pull request on that repository to have it added.

andydotxyz commented 3 years ago

I am quite confident from the questions above that the reported issue is not actually a bug. If you are looking for more general support I would recommend the #fyne channel on gophers Slack.